OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [m68hc11/] [dv-m68hc11tim.c] - Blame information for rev 438

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 24 jeremybenn
/*  dv-m68hc11tim.c -- Simulation of the 68HC11 timer devices.
2
    Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008
3
    Free Software Foundation, Inc.
4
    Written by Stephane Carrez (stcarrez@nerim.fr)
5
    (From a driver model Contributed by Cygnus Solutions.)
6
 
7
    This file is part of the program GDB, the GNU debugger.
8
 
9
    This program is free software; you can redistribute it and/or modify
10
    it under the terms of the GNU General Public License as published by
11
    the Free Software Foundation; either version 3 of the License, or
12
    (at your option) any later version.
13
 
14
    This program is distributed in the hope that it will be useful,
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
    GNU General Public License for more details.
18
 
19
    You should have received a copy of the GNU General Public License
20
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 
22
    */
23
 
24
 
25
#include "sim-main.h"
26
#include "hw-main.h"
27
#include "sim-assert.h"
28
#include <limits.h>
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
 
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
 
59
   */
60
 
61
 
62
 
63
/* port ID's */
64
 
65
enum
66
{
67
  RESET_PORT,
68
  CAPTURE
69
};
70
 
71
 
72
static const struct hw_port_descriptor m68hc11tim_ports[] =
73
{
74
  { "reset",   RESET_PORT, 0, input_port, },
75
  { "capture", CAPTURE,    0, input_port, },
76
  { NULL, },
77
};
78
 
79
 
80
/* Timer Controller information.  */
81
struct 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;
88
  signed64      cop_prev_interrupt;
89
  signed64      rti_prev_interrupt;
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
 
103
static hw_io_read_buffer_method m68hc11tim_io_read_buffer;
104
static hw_io_write_buffer_method m68hc11tim_io_write_buffer;
105
static hw_port_event_method m68hc11tim_port_event;
106
static hw_ioctl_method m68hc11tim_ioctl;
107
 
108
#define M6811_TIMER_FIRST_REG (M6811_TCTN)
109
#define M6811_TIMER_LAST_REG  (M6811_PACNT)
110
 
111
 
112
static void
113
attach_m68hc11tim_regs (struct hw *me,
114
                        struct m68hc11tim *controller)
115
{
116
  hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
117
                     M6811_TIMER_FIRST_REG,
118
                     M6811_TIMER_LAST_REG - M6811_TIMER_FIRST_REG + 1,
119
                     me);
120
}
121
 
122
static void
123
m68hc11tim_finish (struct hw *me)
124
{
125
  struct m68hc11tim *controller;
126
 
127
  controller = HW_ZALLOC (me, struct m68hc11tim);
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
138
 
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
 
148
/* An event arrives on an interrupt port.  */
149
 
150
static void
151
m68hc11tim_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;
161
  unsigned16 tcnt;
162
 
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;
177
            controller->rti_prev_interrupt = 0;
178
          }
179
        if (controller->cop_timer_event)
180
          {
181
            hw_event_queue_deschedule (me, controller->cop_timer_event);
182
            controller->cop_timer_event = 0;
183
            controller->cop_prev_interrupt = 0;
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
197
           the timer events (overflow and RTI clock).  The pending
198
           flags (TFLG2) must be cleared explicitly here.  */
199
        val = 0;
200
        cpu->ios[M6811_TFLG2] = 0;
201
        m68hc11tim_io_write_buffer (me, &val, io_map,
202
                                    (unsigned_word) M6811_TMSK2, 1);
203
        m68hc11tim_io_write_buffer (me, &val, io_map,
204
                                    (unsigned_word) M6811_PACTL, 1);
205
        break;
206
      }
207
 
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
 
226
    default:
227
      hw_abort (me, "Event on unknown port %d", my_port);
228
      break;
229
    }
230
}
231
 
232
enum event_type
233
{
234
  COP_EVENT,
235
  RTI_EVENT,
236
  OVERFLOW_EVENT,
237
  COMPARE_EVENT
238
};
239
 
240
void
241
m68hc11tim_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;
252
  unsigned long tcnt_internal;
253
  unsigned long tcnt, tcnt_prev;
254
  signed64 tcnt_insn_end;
255
  signed64 tcnt_insn_start;
256
  int i;
257
  sim_events *events;
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;
263
  events     = STATE_EVENTS (sd);
264
 
265
  delay = 0;
266
  switch (type)
267
    {
268
    case COP_EVENT:
269
      eventp = &controller->cop_timer_event;
270
      delay  = controller->cop_delay;
271
      delay  = controller->cop_prev_interrupt + controller->cop_delay;
272
      controller->cop_prev_interrupt = delay;
273
      delay  = delay - cpu->cpu_absolute_cycle;
274
      check_interrupt = 1;
275
      delay += events->nr_ticks_to_process;
276
      break;
277
 
278
    case RTI_EVENT:
279
      eventp = &controller->rti_timer_event;
280
      delay  = controller->rti_prev_interrupt + controller->rti_delay;
281
 
282
      if (((long) (data) & 0x0100) == 0)
283
        {
284
          cpu->ios[M6811_TFLG2] |= M6811_RTIF;
285
          check_interrupt = 1;
286
          controller->rti_prev_interrupt = delay;
287
          delay += controller->rti_delay;
288
        }
289
      delay = delay - cpu->cpu_absolute_cycle;
290
      delay += events->nr_ticks_to_process;
291
      break;
292
 
293
    case OVERFLOW_EVENT:
294
      /* Compute the 68HC11 internal free running counter.  */
295
      tcnt_internal = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
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
 
309
      eventp = &controller->tof_timer_event;
310
      if (((long) (data) & 0x100) == 0)
311
        {
312
          cpu->ios[M6811_TFLG2] |= M6811_TOF;
313
          check_interrupt = 1;
314
        }
315
      break;
316
 
317
    case COMPARE_EVENT:
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;
325
 
326
      /* TCNT value at end of current instruction.  */
327
      tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
328
 
329
      /* We must take into account the prescaler that comes
330
         before the counter (it's a power of 2).  */
331
      tcnt_internal = tcnt_insn_end;
332
      tcnt_internal &= 0x0ffff * controller->clock_prescaler;
333
 
334
      flags = cpu->ios[M6811_TMSK1];
335
      mask  = 0x80;
336
      delay = 65536 * controller->clock_prescaler;
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
        {
343
          unsigned long compare;
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))
351
            {
352
              unsigned dt;
353
 
354
              if (compare > tcnt)
355
                dt = 0x10000 - compare - tcnt;
356
              else
357
                dt = tcnt - compare;
358
 
359
              cpu->ios[M6811_TFLG1] |= mask;
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;
366
            }
367
 
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;
374
          else
375
            compare = compare - tcnt_internal
376
              + 65536 * controller->clock_prescaler;
377
 
378
          if (compare < delay)
379
            delay = compare;
380
        }
381
 
382
      /* Deactivate the compare timer if no output compare is enabled.  */
383
      if ((flags & 0xF8) == 0)
384
        delay = 0;
385
      else
386
        delay += events->nr_ticks_to_process;
387
 
388
      eventp = &controller->cmp_timer_event;
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.  */
416
io_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
 
428
io_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
 
440
io_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
 
454
io_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
 
462
io_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
 
472
static double
473
to_realtime (sim_cpu *cpu, signed64 t)
474
{
475
  return (double) (t) / (double) (cpu->cpu_frequency / 4);
476
}
477
 
478
const char*
479
cycle_to_string (sim_cpu *cpu, signed64 t, int flags)
480
{
481
  char time_buf[32];
482
  char cycle_buf[32];
483
  static char buf[64];
484
 
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
    }
499
 
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);
508
  return buf;
509
}
510
 
511
static void
512
m68hc11tim_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;
525
      sim_cpu* cpu;
526
 
527
      cpu = STATE_CPU (sd, 0);
528
 
529
      t  = hw_event_remain_time (me, event);
530
      sim_io_printf (sd, "  Next %s interrupt in %s\n",
531
                     name, cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
532
    }
533
}
534
 
535
static void
536
m68hc11tim_info (struct hw *me)
537
{
538
  SIM_DESC sd;
539
  uint16 base = 0;
540
  sim_cpu *cpu;
541
  struct m68hc11tim *controller;
542
  uint8 val;
543
  uint16 val16;
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
 
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
 
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
 
615
  val = cpu->ios[M6811_PACNT];
616
  print_io_byte (sd, "PACNT", 0, val, base + M6811_PACNT);
617
  sim_io_printf (sd, "\n");
618
 
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
 
626
static int
627
m68hc11tim_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
 
637
static unsigned
638
m68hc11tim_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;
648
  unsigned cnt = 0;
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
 
656
  while (nr_bytes)
657
    {
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;
667
 
668
        case M6811_TCTN_L:
669
          val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust)
670
                         / controller->clock_prescaler);
671
          break;
672
 
673
        default:
674
          val = cpu->ios[base];
675
          break;
676
        }
677
      *((unsigned8*) dest) = val;
678
      dest = (char*) dest + 1;
679
      base++;
680
      nr_bytes--;
681
      cnt++;
682
    }
683
  return cnt;
684
}
685
 
686
static unsigned
687
m68hc11tim_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;
699
  int reset_overflow = 0;
700
  int cnt = 0;
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);
707
 
708
  while (nr_bytes)
709
    {
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;
727
 
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;
738
 
739
        case M6811_TMSK2:
740
 
741
          /* Timer prescaler cannot be changed after 64 bus cycles.  */
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);
770
          break;
771
 
772
        case M6811_PACTL:
773
          n = (1 << ((val & (M6811_RTR1 | M6811_RTR0))));
774
          cpu->ios[base] = val;
775
 
776
          controller->rti_delay = (long) (n) * 8192;
777
          m68hc11tim_timer_event (me, (void*) (RTI_EVENT| 0x100));
778
          break;
779
 
780
        case M6811_TFLG2:
781
          val &= cpu->ios[M6811_TFLG2];
782
          cpu->ios[M6811_TFLG2] &= ~val;
783
          interrupts_update_pending (&cpu->cpu_interrupts);
784
          break;
785
 
786
        case M6811_TMSK1:
787
          cpu->ios[M6811_TMSK1] = val;
788
          interrupts_update_pending (&cpu->cpu_interrupts);
789
          reset_compare = 1;
790
          break;
791
 
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
 
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;
806
 
807
        case M6811_TCTL1:
808
        case M6811_TCTL2:
809
          cpu->ios[base] = val;
810
          break;
811
 
812
        default:
813
          cpu->ios[base] = val;
814
          break;
815
        }
816
 
817
      base++;
818
      nr_bytes--;
819
      cnt++;
820
      source = (char*) source + 1;
821
    }
822
 
823
  /* Re-compute the next timer compare event.  */
824
  if (reset_compare)
825
    {
826
      m68hc11tim_timer_event (me, (void*) (COMPARE_EVENT));
827
    }
828
  if (reset_overflow)
829
    {
830
      m68hc11tim_timer_event (me, (void*) (OVERFLOW_EVENT| 0x100));
831
    }
832
  return cnt;
833
}
834
 
835
 
836
const struct hw_descriptor dv_m68hc11tim_descriptor[] = {
837
  { "m68hc11tim", m68hc11tim_finish },
838
  { "m68hc12tim", m68hc11tim_finish },
839
  { NULL },
840
};
841
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.