]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m68hc11/dv-m68hc11tim.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11tim.c
CommitLineData
e0709f50 1/* dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
1d506c26 2 Copyright (C) 1999-2024 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>
600ddfd5
MF
30
31#include "m68hc11-sim.h"
e0709f50
AC
32
33/* DEVICE
34
35 m68hc11tim - m68hc11 timer devices
36
37
38 DESCRIPTION
39
40 Implements the m68hc11 timer as described in Chapter 10
41 of the pink book.
42
43
44 PROPERTIES
45
46 none
47
48
49 PORTS
50
51 reset (input)
52
53 Reset the timer device. This port must be connected to
54 the cpu-reset output port.
55
827ec39a
SC
56 capture (input)
57
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.
61
e0709f50
AC
62 */
63
64
65
66/* port ID's */
67
68enum
69{
827ec39a
SC
70 RESET_PORT,
71 CAPTURE
e0709f50
AC
72};
73
74
75static const struct hw_port_descriptor m68hc11tim_ports[] =
76{
827ec39a
SC
77 { "reset", RESET_PORT, 0, input_port, },
78 { "capture", CAPTURE, 0, input_port, },
e0709f50
AC
79 { NULL, },
80};
81
82
83/* Timer Controller information. */
84struct m68hc11tim
85{
86 unsigned long cop_delay;
87 unsigned long rti_delay;
88 unsigned long ovf_delay;
7606e1a3
MF
89 int64_t clock_prescaler;
90 int64_t tcnt_adjust;
91 int64_t cop_prev_interrupt;
92 int64_t rti_prev_interrupt;
e0709f50
AC
93
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;
99};
100
101
102
103/* Finish off the partially created hw device. Attach our local
104 callbacks. Wire up our port names etc. */
105
106static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
107static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
108static hw_port_event_method m68hc11tim_port_event;
109static hw_ioctl_method m68hc11tim_ioctl;
110
111#define M6811_TIMER_FIRST_REG (M6811_TCTN)
112#define M6811_TIMER_LAST_REG (M6811_PACNT)
113
114
115static void
116attach_m68hc11tim_regs (struct hw *me,
117 struct m68hc11tim *controller)
118{
63348d04 119 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
e0709f50
AC
120 M6811_TIMER_FIRST_REG,
121 M6811_TIMER_LAST_REG - M6811_TIMER_FIRST_REG + 1,
122 me);
123}
124
e0709f50
AC
125static void
126m68hc11tim_finish (struct hw *me)
127{
128 struct m68hc11tim *controller;
129
130 controller = HW_ZALLOC (me, struct m68hc11tim);
e0709f50
AC
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);
136#ifdef set_hw_ioctl
137 set_hw_ioctl (me, m68hc11tim_ioctl);
138#else
139 me->to_ioctl = m68hc11tim_ioctl;
140#endif
b93775f5 141
e0709f50
AC
142 /* Preset defaults. */
143 controller->clock_prescaler = 1;
144 controller->tcnt_adjust = 0;
145
146 /* Attach ourself to our parent bus. */
147 attach_m68hc11tim_regs (me, controller);
148}
149
150
e0709f50
AC
151/* An event arrives on an interrupt port. */
152
153static void
154m68hc11tim_port_event (struct hw *me,
155 int my_port,
156 struct hw *source,
157 int source_port,
158 int level)
159{
160 SIM_DESC sd;
161 struct m68hc11tim *controller;
162 sim_cpu *cpu;
79d784ae 163 struct m68hc11_sim_cpu *m68hc11_cpu;
7606e1a3
MF
164 uint8_t val;
165 uint16_t tcnt;
827ec39a 166
e0709f50
AC
167 controller = hw_data (me);
168 sd = hw_system (me);
169 cpu = STATE_CPU (sd, 0);
79d784ae 170 m68hc11_cpu = M68HC11_SIM_CPU (cpu);
e0709f50
AC
171 switch (my_port)
172 {
173 case RESET_PORT:
174 {
175 HW_TRACE ((me, "Timer reset"));
176
177 /* Cancel all timer events. */
178 if (controller->rti_timer_event)
179 {
180 hw_event_queue_deschedule (me, controller->rti_timer_event);
181 controller->rti_timer_event = 0;
401493c8 182 controller->rti_prev_interrupt = 0;
e0709f50
AC
183 }
184 if (controller->cop_timer_event)
185 {
186 hw_event_queue_deschedule (me, controller->cop_timer_event);
187 controller->cop_timer_event = 0;
401493c8 188 controller->cop_prev_interrupt = 0;
e0709f50
AC
189 }
190 if (controller->tof_timer_event)
191 {
192 hw_event_queue_deschedule (me, controller->tof_timer_event);
193 controller->tof_timer_event = 0;
194 }
195 if (controller->cmp_timer_event)
196 {
197 hw_event_queue_deschedule (me, controller->cmp_timer_event);
198 controller->cmp_timer_event = 0;
199 }
200
201 /* Reset the state of Timer registers. This also restarts
86596dc8
SC
202 the timer events (overflow and RTI clock). The pending
203 flags (TFLG2) must be cleared explicitly here. */
e0709f50 204 val = 0;
79d784ae 205 m68hc11_cpu->ios[M6811_TFLG2] = 0;
e0709f50
AC
206 m68hc11tim_io_write_buffer (me, &val, io_map,
207 (unsigned_word) M6811_TMSK2, 1);
e0709f50
AC
208 m68hc11tim_io_write_buffer (me, &val, io_map,
209 (unsigned_word) M6811_PACTL, 1);
210 break;
211 }
212
827ec39a 213 case CAPTURE:
79d784ae 214 tcnt = (uint16_t) ((m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust)
827ec39a
SC
215 / controller->clock_prescaler);
216 switch (level)
217 {
218 case M6811_TIC1:
219 case M6811_TIC2:
220 case M6811_TIC3:
79d784ae
MF
221 m68hc11_cpu->ios[level] = tcnt >> 8;
222 m68hc11_cpu->ios[level + 1] = tcnt;
827ec39a
SC
223 break;
224
225 default:
226 hw_abort (me, "Invalid event parameter %d", level);
227 break;
228 }
229 break;
230
e0709f50
AC
231 default:
232 hw_abort (me, "Event on unknown port %d", my_port);
233 break;
234 }
235}
236
237enum event_type
238{
239 COP_EVENT,
240 RTI_EVENT,
241 OVERFLOW_EVENT,
242 COMPARE_EVENT
243};
244
527aaa4a 245static void
e0709f50
AC
246m68hc11tim_timer_event (struct hw *me, void *data)
247{
248 SIM_DESC sd;
249 struct m68hc11tim *controller;
250 sim_cpu *cpu;
79d784ae 251 struct m68hc11_sim_cpu *m68hc11_cpu;
e0709f50
AC
252 enum event_type type;
253 unsigned long delay;
254 struct hw_event **eventp;
255 int check_interrupt = 0;
256 unsigned mask;
257 unsigned flags;
401493c8 258 unsigned long tcnt_internal;
a685700c 259 unsigned long tcnt, tcnt_prev;
7606e1a3
MF
260 int64_t tcnt_insn_end;
261 int64_t tcnt_insn_start;
e0709f50 262 int i;
401493c8 263 sim_events *events;
e0709f50
AC
264
265 controller = hw_data (me);
266 sd = hw_system (me);
267 cpu = STATE_CPU (sd, 0);
79d784ae 268 m68hc11_cpu = M68HC11_SIM_CPU (cpu);
06969ac4 269 type = (enum event_type) ((uintptr_t) data) & 0x0FF;
401493c8 270 events = STATE_EVENTS (sd);
e0709f50
AC
271
272 delay = 0;
273 switch (type)
274 {
275 case COP_EVENT:
276 eventp = &controller->cop_timer_event;
277 delay = controller->cop_delay;
401493c8
SC
278 delay = controller->cop_prev_interrupt + controller->cop_delay;
279 controller->cop_prev_interrupt = delay;
79d784ae 280 delay = delay - m68hc11_cpu->cpu_absolute_cycle;
e0709f50 281 check_interrupt = 1;
401493c8 282 delay += events->nr_ticks_to_process;
e0709f50
AC
283 break;
284
285 case RTI_EVENT:
286 eventp = &controller->rti_timer_event;
401493c8
SC
287 delay = controller->rti_prev_interrupt + controller->rti_delay;
288
06969ac4 289 if (((uintptr_t) data & 0x0100) == 0)
e0709f50 290 {
79d784ae 291 m68hc11_cpu->ios[M6811_TFLG2] |= M6811_RTIF;
e0709f50 292 check_interrupt = 1;
401493c8
SC
293 controller->rti_prev_interrupt = delay;
294 delay += controller->rti_delay;
e0709f50 295 }
79d784ae 296 delay = delay - m68hc11_cpu->cpu_absolute_cycle;
401493c8 297 delay += events->nr_ticks_to_process;
e0709f50
AC
298 break;
299
300 case OVERFLOW_EVENT:
a685700c 301 /* Compute the 68HC11 internal free running counter. */
79d784ae 302 tcnt_internal = (m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust);
401493c8
SC
303
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;
307
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;
311
312 /* The 'nr_ticks_to_process' will be subtracted when the event
313 is scheduled. */
314 delay += events->nr_ticks_to_process;
315
e0709f50 316 eventp = &controller->tof_timer_event;
06969ac4 317 if (((uintptr_t) data & 0x100) == 0)
401493c8 318 {
79d784ae 319 m68hc11_cpu->ios[M6811_TFLG2] |= M6811_TOF;
401493c8
SC
320 check_interrupt = 1;
321 }
e0709f50
AC
322 break;
323
324 case COMPARE_EVENT:
a685700c
SC
325 /* Compute value of TCNT register (64-bit precision) at beginning
326 and end of instruction. */
79d784ae
MF
327 tcnt_insn_end = (m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust);
328 tcnt_insn_start = (tcnt_insn_end - m68hc11_cpu->cpu_current_cycle);
a685700c
SC
329
330 /* TCNT value at beginning of current instruction. */
331 tcnt_prev = (tcnt_insn_start / controller->clock_prescaler) & 0x0ffff;
e0709f50 332
a685700c
SC
333 /* TCNT value at end of current instruction. */
334 tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
401493c8
SC
335
336 /* We must take into account the prescaler that comes
337 before the counter (it's a power of 2). */
a685700c 338 tcnt_internal = tcnt_insn_end;
401493c8
SC
339 tcnt_internal &= 0x0ffff * controller->clock_prescaler;
340
79d784ae 341 flags = m68hc11_cpu->ios[M6811_TMSK1];
e0709f50 342 mask = 0x80;
401493c8 343 delay = 65536 * controller->clock_prescaler;
e0709f50
AC
344
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)
349 {
401493c8 350 unsigned long compare;
a685700c 351
79d784ae 352 compare = (m68hc11_cpu->ios[i] << 8) + m68hc11_cpu->ios[i + 1];
a685700c
SC
353
354 /* See if compare is reached; handle wrap arround. */
355 if ((compare >= tcnt_prev && compare <= tcnt && tcnt_prev < tcnt)
356 || (compare >= tcnt_prev && tcnt_prev > tcnt)
357 || (compare < tcnt && tcnt_prev > tcnt))
e0709f50 358 {
a685700c
SC
359 unsigned dt;
360
361 if (compare > tcnt)
362 dt = 0x10000 - compare - tcnt;
363 else
364 dt = tcnt - compare;
365
79d784ae 366 m68hc11_cpu->ios[M6811_TFLG1] |= mask;
a685700c
SC
367
368 /* Raise interrupt now at the correct CPU cycle so that
369 we can find the interrupt latency. */
79d784ae
MF
370 m68hc11_cpu->cpu_absolute_cycle -= dt;
371 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
372 m68hc11_cpu->cpu_absolute_cycle += dt;
e0709f50
AC
373 }
374
401493c8
SC
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;
e0709f50 381 else
401493c8
SC
382 compare = compare - tcnt_internal
383 + 65536 * controller->clock_prescaler;
a685700c 384
e0709f50
AC
385 if (compare < delay)
386 delay = compare;
387 }
e0709f50
AC
388
389 /* Deactivate the compare timer if no output compare is enabled. */
a685700c 390 if ((flags & 0xF8) == 0)
e0709f50 391 delay = 0;
a685700c
SC
392 else
393 delay += events->nr_ticks_to_process;
394
395 eventp = &controller->cmp_timer_event;
e0709f50
AC
396 break;
397
398 default:
399 eventp = 0;
400 break;
401 }
402
403 if (*eventp)
404 {
405 hw_event_queue_deschedule (me, *eventp);
406 *eventp = 0;
407 }
408
409 if (delay != 0)
410 {
411 *eventp = hw_event_queue_schedule (me, delay,
412 m68hc11tim_timer_event,
413 (void*) type);
414 }
415
416 if (check_interrupt)
79d784ae 417 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
e0709f50
AC
418}
419
420
421/* Descriptions of the Timer I/O ports. These descriptions are only used to
422 give information of the Timer device under GDB. */
962e9d85
SC
423io_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" },
432 { 0, 0, 0 }
433};
434
435io_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" },
444 { 0, 0, 0 }
445};
446
e0709f50
AC
447io_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" },
458 { 0, 0, 0 }
459};
460
461io_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" },
466 { 0, 0, 0 }
467};
468
469io_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)" },
476 { 0, 0, 0 }
477};
478
479static double
7606e1a3 480to_realtime (sim_cpu *cpu, int64_t t)
e0709f50 481{
79d784ae 482 return (double) (t) / (double) (M68HC11_SIM_CPU (cpu)->cpu_frequency / 4);
e0709f50
AC
483}
484
2990a9f4 485const char*
7606e1a3 486cycle_to_string (sim_cpu *cpu, int64_t t, int flags)
2990a9f4 487{
a685700c
SC
488 char time_buf[32];
489 char cycle_buf[32];
8a16cc4b
MF
490 /* Big enough to handle 64-bit t, time_buf, and cycle_buf. */
491 static char buf[128];
86596dc8 492
a685700c
SC
493 time_buf[0] = 0;
494 cycle_buf[0] = 0;
495 if (flags & PRINT_TIME)
496 {
497 double dt;
498
499 dt = to_realtime (cpu, t);
500 if (dt < 0.001)
501 sprintf (time_buf, " (%3.1f us)", dt * 1000000.0);
502 else if (dt < 1.0)
503 sprintf (time_buf, " (%3.1f ms)", dt * 1000.0);
504 else
505 sprintf (time_buf, " (%3.1f s)", dt);
506 }
2990a9f4 507
a685700c
SC
508 if (flags & PRINT_CYCLE)
509 sprintf (cycle_buf, " cycle%s",
510 (t > 1 ? "s" : ""));
511
8a16cc4b 512 sprintf (buf, "%9" PRIi64 "%s%s", t, cycle_buf, time_buf);
2990a9f4
SC
513 return buf;
514}
515
e0709f50
AC
516static void
517m68hc11tim_print_timer (struct hw *me, const char *name,
518 struct hw_event *event)
519{
520 SIM_DESC sd;
521
522 sd = hw_system (me);
523 if (event == 0)
524 {
525 sim_io_printf (sd, " No %s interrupt will be raised.\n", name);
526 }
527 else
528 {
7606e1a3 529 int64_t t;
6f64fd48 530 sim_cpu *cpu;
e0709f50
AC
531
532 cpu = STATE_CPU (sd, 0);
533
534 t = hw_event_remain_time (me, event);
2990a9f4 535 sim_io_printf (sd, " Next %s interrupt in %s\n",
a685700c 536 name, cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
e0709f50
AC
537 }
538}
539
540static void
541m68hc11tim_info (struct hw *me)
542{
543 SIM_DESC sd;
7606e1a3 544 uint16_t base = 0;
e0709f50 545 sim_cpu *cpu;
79d784ae 546 struct m68hc11_sim_cpu *m68hc11_cpu;
e0709f50 547 struct m68hc11tim *controller;
7606e1a3
MF
548 uint8_t val;
549 uint16_t val16;
e0709f50
AC
550
551 sd = hw_system (me);
552 cpu = STATE_CPU (sd, 0);
79d784ae 553 m68hc11_cpu = M68HC11_SIM_CPU (cpu);
e0709f50
AC
554 controller = hw_data (me);
555
556 sim_io_printf (sd, "M68HC11 Timer:\n");
557
558 base = cpu_get_io_base (cpu);
559
962e9d85 560 /* Info for TIC1 */
79d784ae 561 val16 = (m68hc11_cpu->ios[M6811_TIC1_H] << 8) + m68hc11_cpu->ios[M6811_TIC1_L];
962e9d85
SC
562 print_io_word (sd, "TIC1 ", 0, val16, base + M6811_TIC1);
563 sim_io_printf (sd, "\n");
564
565 /* Info for TIC2 */
79d784ae 566 val16 = (m68hc11_cpu->ios[M6811_TIC2_H] << 8) + m68hc11_cpu->ios[M6811_TIC2_L];
962e9d85
SC
567 print_io_word (sd, "TIC2 ", 0, val16, base + M6811_TIC2);
568 sim_io_printf (sd, "\n");
569
570 /* Info for TIC3 */
79d784ae 571 val16 = (m68hc11_cpu->ios[M6811_TIC3_H] << 8) + m68hc11_cpu->ios[M6811_TIC3_L];
962e9d85
SC
572 print_io_word (sd, "TIC3 ", 0, val16, base + M6811_TIC3);
573 sim_io_printf (sd, "\n");
574
575 /* Info for TOC1 */
79d784ae 576 val16 = (m68hc11_cpu->ios[M6811_TOC1_H] << 8) + m68hc11_cpu->ios[M6811_TOC1_L];
962e9d85
SC
577 print_io_word (sd, "TOC1 ", 0, val16, base + M6811_TOC1);
578 sim_io_printf (sd, "\n");
579
580 /* Info for TOC2 */
79d784ae 581 val16 = (m68hc11_cpu->ios[M6811_TOC2_H] << 8) + m68hc11_cpu->ios[M6811_TOC2_L];
962e9d85
SC
582 print_io_word (sd, "TOC2 ", 0, val16, base + M6811_TOC2);
583 sim_io_printf (sd, "\n");
584
585 /* Info for TOC3 */
79d784ae 586 val16 = (m68hc11_cpu->ios[M6811_TOC3_H] << 8) + m68hc11_cpu->ios[M6811_TOC3_L];
962e9d85
SC
587 print_io_word (sd, "TOC3 ", 0, val16, base + M6811_TOC3);
588 sim_io_printf (sd, "\n");
589
590 /* Info for TOC4 */
79d784ae 591 val16 = (m68hc11_cpu->ios[M6811_TOC4_H] << 8) + m68hc11_cpu->ios[M6811_TOC4_L];
962e9d85
SC
592 print_io_word (sd, "TOC4 ", 0, val16, base + M6811_TOC4);
593 sim_io_printf (sd, "\n");
594
595 /* Info for TOC5 */
79d784ae 596 val16 = (m68hc11_cpu->ios[M6811_TOC5_H] << 8) + m68hc11_cpu->ios[M6811_TOC5_L];
962e9d85
SC
597 print_io_word (sd, "TOC5 ", 0, val16, base + M6811_TOC5);
598 sim_io_printf (sd, "\n");
599
600 /* Info for TMSK1 */
79d784ae 601 val = m68hc11_cpu->ios[M6811_TMSK1];
962e9d85
SC
602 print_io_byte (sd, "TMSK1 ", tmsk1_desc, val, base + M6811_TMSK1);
603 sim_io_printf (sd, "\n");
604
605 /* Info for TFLG1 */
79d784ae 606 val = m68hc11_cpu->ios[M6811_TFLG1];
962e9d85
SC
607 print_io_byte (sd, "TFLG1", tflg1_desc, val, base + M6811_TFLG1);
608 sim_io_printf (sd, "\n");
609
79d784ae 610 val = m68hc11_cpu->ios[M6811_TMSK2];
e0709f50
AC
611 print_io_byte (sd, "TMSK2 ", tmsk2_desc, val, base + M6811_TMSK2);
612 sim_io_printf (sd, "\n");
613
79d784ae 614 val = m68hc11_cpu->ios[M6811_TFLG2];
e0709f50
AC
615 print_io_byte (sd, "TFLG2", tflg2_desc, val, base + M6811_TFLG2);
616 sim_io_printf (sd, "\n");
617
79d784ae 618 val = m68hc11_cpu->ios[M6811_PACTL];
e0709f50
AC
619 print_io_byte (sd, "PACTL", pactl_desc, val, base + M6811_PACTL);
620 sim_io_printf (sd, "\n");
621
79d784ae 622 val = m68hc11_cpu->ios[M6811_PACNT];
86596dc8
SC
623 print_io_byte (sd, "PACNT", 0, val, base + M6811_PACNT);
624 sim_io_printf (sd, "\n");
625
e0709f50
AC
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);
631}
632
633static int
634m68hc11tim_ioctl (struct hw *me,
635 hw_ioctl_request request,
636 va_list ap)
637{
638 m68hc11tim_info (me);
639 return 0;
640}
641
642/* generic read/write */
643
644static unsigned
645m68hc11tim_io_read_buffer (struct hw *me,
646 void *dest,
647 int space,
648 unsigned_word base,
649 unsigned nr_bytes)
650{
651 SIM_DESC sd;
652 struct m68hc11tim *controller;
653 sim_cpu *cpu;
79d784ae 654 struct m68hc11_sim_cpu *m68hc11_cpu;
7606e1a3 655 uint8_t val;
401493c8 656 unsigned cnt = 0;
e0709f50
AC
657
658 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
659
660 sd = hw_system (me);
661 cpu = STATE_CPU (sd, 0);
79d784ae 662 m68hc11_cpu = M68HC11_SIM_CPU (cpu);
e0709f50
AC
663 controller = hw_data (me);
664
401493c8 665 while (nr_bytes)
e0709f50 666 {
401493c8
SC
667 switch (base)
668 {
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. */
672 case M6811_TCTN_H:
79d784ae
MF
673 val = (uint8_t) ((m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust)
674 / (controller->clock_prescaler * 256));
401493c8 675 break;
e0709f50 676
401493c8 677 case M6811_TCTN_L:
79d784ae
MF
678 val = (uint8_t) ((m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust)
679 / controller->clock_prescaler);
401493c8 680 break;
e0709f50 681
401493c8 682 default:
79d784ae 683 val = m68hc11_cpu->ios[base];
401493c8
SC
684 break;
685 }
7606e1a3 686 *((uint8_t*) dest) = val;
a685700c 687 dest = (char*) dest + 1;
401493c8
SC
688 base++;
689 nr_bytes--;
690 cnt++;
e0709f50 691 }
401493c8 692 return cnt;
e0709f50
AC
693}
694
695static unsigned
696m68hc11tim_io_write_buffer (struct hw *me,
697 const void *source,
698 int space,
699 unsigned_word base,
700 unsigned nr_bytes)
701{
702 SIM_DESC sd;
703 struct m68hc11tim *controller;
704 sim_cpu *cpu;
79d784ae 705 struct m68hc11_sim_cpu *m68hc11_cpu;
7606e1a3
MF
706 uint8_t val, n;
707 int64_t adj;
e0709f50 708 int reset_compare = 0;
401493c8
SC
709 int reset_overflow = 0;
710 int cnt = 0;
e0709f50
AC
711
712 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
713
714 sd = hw_system (me);
715 cpu = STATE_CPU (sd, 0);
79d784ae 716 m68hc11_cpu = M68HC11_SIM_CPU (cpu);
e0709f50 717 controller = hw_data (me);
401493c8
SC
718
719 while (nr_bytes)
e0709f50 720 {
7606e1a3 721 val = *((const uint8_t*) source);
401493c8
SC
722 switch (base)
723 {
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. */
728 case M6811_TCTN_L:
79d784ae 729 adj = ((m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust)
7606e1a3 730 / (controller->clock_prescaler * (int64_t) 256)) & 0x0FF;
79d784ae 731 adj = m68hc11_cpu->cpu_absolute_cycle
7606e1a3
MF
732 - (adj * controller->clock_prescaler * (int64_t) 256)
733 - ((int64_t) adj * controller->clock_prescaler);
401493c8
SC
734 controller->tcnt_adjust = adj;
735 reset_compare = 1;
736 reset_overflow = 1;
737 break;
e0709f50 738
401493c8 739 case M6811_TCTN_H:
79d784ae 740 adj = ((m68hc11_cpu->cpu_absolute_cycle - controller->tcnt_adjust)
401493c8 741 / controller->clock_prescaler) & 0x0ff;
79d784ae 742 adj = m68hc11_cpu->cpu_absolute_cycle
7606e1a3 743 - ((int64_t) val * controller->clock_prescaler * (int64_t) 256)
401493c8
SC
744 - (adj * controller->clock_prescaler);
745 controller->tcnt_adjust = adj;
746 reset_compare = 1;
747 reset_overflow = 1;
748 break;
e0709f50 749
401493c8 750 case M6811_TMSK2:
e0709f50 751
86596dc8 752 /* Timer prescaler cannot be changed after 64 bus cycles. */
79d784ae 753 if (m68hc11_cpu->cpu_absolute_cycle >= 64)
401493c8
SC
754 {
755 val &= ~(M6811_PR1 | M6811_PR0);
79d784ae 756 val |= m68hc11_cpu->ios[M6811_TMSK2] & (M6811_PR1 | M6811_PR0);
401493c8
SC
757 }
758 switch (val & (M6811_PR1 | M6811_PR0))
759 {
760 case 0:
761 n = 1;
762 break;
763 case M6811_PR0:
764 n = 4;
765 break;
766 case M6811_PR1:
767 n = 8;
768 break;
769 default:
770 case M6811_PR1 | M6811_PR0:
771 n = 16;
772 break;
773 }
79d784ae 774 if (m68hc11_cpu->cpu_absolute_cycle < 64)
401493c8
SC
775 {
776 reset_overflow = 1;
777 controller->clock_prescaler = n;
778 }
79d784ae
MF
779 m68hc11_cpu->ios[base] = val;
780 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
e0709f50 781 break;
e0709f50 782
401493c8
SC
783 case M6811_PACTL:
784 n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
79d784ae 785 m68hc11_cpu->ios[base] = val;
e0709f50 786
401493c8
SC
787 controller->rti_delay = (long) (n) * 8192;
788 m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
789 break;
e0709f50 790
401493c8 791 case M6811_TFLG2:
79d784ae
MF
792 val &= m68hc11_cpu->ios[M6811_TFLG2];
793 m68hc11_cpu->ios[M6811_TFLG2] &= ~val;
794 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
86596dc8 795 break;
e0709f50 796
86596dc8 797 case M6811_TMSK1:
79d784ae
MF
798 m68hc11_cpu->ios[M6811_TMSK1] = val;
799 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
a685700c 800 reset_compare = 1;
401493c8 801 break;
e0709f50 802
86596dc8 803 case M6811_TFLG1:
79d784ae
MF
804 val &= m68hc11_cpu->ios[M6811_TFLG1];
805 m68hc11_cpu->ios[M6811_TFLG1] &= ~val;
806 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
86596dc8
SC
807 break;
808
401493c8
SC
809 case M6811_TOC1:
810 case M6811_TOC2:
811 case M6811_TOC3:
812 case M6811_TOC4:
813 case M6811_TOC5:
79d784ae 814 m68hc11_cpu->ios[base] = val;
401493c8
SC
815 reset_compare = 1;
816 break;
a685700c 817
86596dc8
SC
818 case M6811_TCTL1:
819 case M6811_TCTL2:
79d784ae 820 m68hc11_cpu->ios[base] = val;
86596dc8
SC
821 break;
822
401493c8 823 default:
79d784ae 824 m68hc11_cpu->ios[base] = val;
401493c8
SC
825 break;
826 }
827
828 base++;
829 nr_bytes--;
830 cnt++;
a685700c 831 source = (char*) source + 1;
e0709f50
AC
832 }
833
834 /* Re-compute the next timer compare event. */
835 if (reset_compare)
836 {
837 m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
838 }
401493c8
SC
839 if (reset_overflow)
840 {
841 m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
842 }
843 return cnt;
e0709f50
AC
844}
845
846
847const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
b93775f5
SC
848 { "m68hc11tim", m68hc11tim_finish },
849 { "m68hc12tim", m68hc11tim_finish },
e0709f50
AC
850 { NULL },
851};
852