Support R_SPARC_WDISP10 and R_SPARC_H34.
[external/binutils.git] / sim / mips / dv-tx3904tmr.c
1 /*  This file is part of the program GDB, the GNU debugger.
2     
3     Copyright (C) 1998, 2007-2012 Free Software Foundation, Inc.
4     Contributed by Cygnus Solutions.
5     
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18     
19     */
20
21
22 #include "sim-main.h"
23 #include "hw-main.h"
24
25
26 /* DEVICE
27
28    
29    tx3904tmr - tx3904 timer
30
31    
32    DESCRIPTION
33
34    
35    Implements one tx3904 timer/counter described in the tx3904
36    user guide.  Three instances are required for TMR0, TMR1, and
37    TMR3 within the tx3904, at different base addresses.  
38
39    Both internal and system clocks are synthesized as divided versions
40    of the simulator clock.
41    
42    There is no support for:
43     - edge sensitivity of external clock
44     - different mode restrictions for TMR0..2
45     - level interrupts (interrupts are treated as events that occur at edges)
46
47
48
49    PROPERTIES
50
51
52    reg <base> <length>
53
54    Base of TMR control register bank.  <length> must equal 0x100.
55    Register offsets:       0: TCR: timer control  register
56                            4: TISR: timer interrupt status register
57                            8: CPRA: compare register A
58                           12: CPRB: compare register B
59                           16: ITMR: interval timer mode register
60                           32: CCDR: divider register
61                           48: PMGR: pulse generator mode register
62                           64: WTMR: watchdog timer mode register
63                          240: TRR: timer read register
64
65
66    clock <ticks>
67
68    Rate of timer clock signal.  This number is the number of simulator
69    ticks per clock signal tick.  Default 1.
70
71    
72    ext <ticks>
73
74    Rate of "external input clock signal", the other clock input of the
75    timer.  It uses the same scale as above.  Default 100.
76
77
78
79    PORTS
80
81
82    int (output)
83
84    Interrupt port.  An event is generated when a timer interrupt
85    occurs.
86
87
88    ff (output)
89
90    Flip-flop output, corresponds to the TMFFOUT port.  An event is
91    generated when flip-flop changes value.  The integer associated
92    with the event is 1/0 according to flip-flop value.
93
94
95    reset (input)
96
97    Reset port.
98
99    */
100
101
102
103 /* static functions */
104
105 static void deliver_tx3904tmr_tick (struct hw *me, void *data);
106
107
108 /* register numbers; each is one word long */
109 enum 
110 {
111   TCR_REG = 0,
112   TISR_REG = 1,
113   CPRA_REG = 2,
114   CPRB_REG = 3,
115   ITMR_REG = 4,
116   CCDR_REG = 8,
117   PMGR_REG = 12,
118   WTMR_REG = 16,
119   TRR_REG = 60
120 };
121
122
123
124 /* port ID's */
125
126 enum
127  {
128   RESET_PORT,
129   INT_PORT,
130   FF_PORT
131 };
132
133
134 static const struct hw_port_descriptor tx3904tmr_ports[] = 
135 {
136   { "int", INT_PORT, 0, output_port, },
137   { "ff", FF_PORT, 0, output_port, },
138   { "reset", RESET_PORT, 0, input_port, },
139   { NULL, },
140 };
141
142
143
144 /* The timer/counter register internal state.  Note that we store
145    state using the control register images, in host endian order. */
146
147 struct tx3904tmr {
148   address_word base_address; /* control register base */
149   unsigned_4 clock_ticks, ext_ticks; /* clock frequencies */
150   signed_8 last_ticks; /* time at last deliver_*_tick call */
151   signed_8 roundoff_ticks; /* sim ticks unprocessed during last tick call */
152   int ff; /* pulse generator flip-flop value: 1/0 */
153   struct hw_event* event; /* last scheduled event */
154
155   unsigned_4 tcr;
156 #define GET_TCR_TCE(c)      (((c)->tcr & 0x80) >> 7)
157 #define GET_TCR_CCDE(c)     (((c)->tcr & 0x40) >> 6)
158 #define GET_TCR_CRE(c)      (((c)->tcr & 0x20) >> 5)
159 #define GET_TCR_CCS(c)      (((c)->tcr & 0x04) >> 2)
160 #define GET_TCR_TMODE(c)    (((c)->tcr & 0x03) >> 0)
161   unsigned_4 tisr;
162 #define SET_TISR_TWIS(c)    ((c)->tisr |= 0x08)
163 #define SET_TISR_TPIBS(c)   ((c)->tisr |= 0x04)
164 #define SET_TISR_TPIAS(c)   ((c)->tisr |= 0x02)
165 #define SET_TISR_TIIS(c)    ((c)->tisr |= 0x01)
166   unsigned_4 cpra;
167   unsigned_4 cprb;
168   unsigned_4 itmr;
169 #define GET_ITMR_TIIE(c)    (((c)->itmr & 0x8000) >> 15)
170 #define SET_ITMR_TIIE(c,v)  BLIT32((c)->itmr, 15, (v) ? 1 : 0)
171 #define GET_ITMR_TZCE(c)    (((c)->itmr & 0x0001) >> 0)
172 #define SET_ITMR_TZCE(c,v)  BLIT32((c)->itmr, 0, (v) ? 1 : 0)
173   unsigned_4 ccdr;
174 #define GET_CCDR_CDR(c)     (((c)->ccdr & 0x07) >> 0)
175   unsigned_4 pmgr;
176 #define GET_PMGR_TPIBE(c)   (((c)->pmgr & 0x8000) >> 15)
177 #define SET_PMGR_TPIBE(c,v) BLIT32((c)->pmgr, 15, (v) ? 1 : 0)
178 #define GET_PMGR_TPIAE(c)   (((c)->pmgr & 0x4000) >> 14)
179 #define SET_PMGR_TPIAE(c,v) BLIT32((c)->pmgr, 14, (v) ? 1 : 0)
180 #define GET_PMGR_FFI(c)     (((c)->pmgr & 0x0001) >> 0)
181 #define SET_PMGR_FFI(c,v)   BLIT32((c)->pmgr, 0, (v) ? 1 : 0)
182   unsigned_4 wtmr;
183 #define GET_WTMR_TWIE(c)    (((c)->wtmr & 0x8000) >> 15)
184 #define SET_WTMR_TWIE(c,v)  BLIT32((c)->wtmr, 15, (v) ? 1 : 0)
185 #define GET_WTMR_WDIS(c)    (((c)->wtmr & 0x0080) >> 7)
186 #define SET_WTMR_WDIS(c,v)  BLIT32((c)->wtmr, 7, (v) ? 1 : 0)
187 #define GET_WTMR_TWC(c)     (((c)->wtmr & 0x0001) >> 0)
188 #define SET_WTMR_TWC(c,v)   BLIT32((c)->wtmr, 0, (v) ? 1 : 0)
189   unsigned_4 trr;
190 };
191
192
193
194 /* Finish off the partially created hw device.  Attach our local
195    callbacks.  Wire up our port names etc */
196
197 static hw_io_read_buffer_method tx3904tmr_io_read_buffer;
198 static hw_io_write_buffer_method tx3904tmr_io_write_buffer;
199 static hw_port_event_method tx3904tmr_port_event;
200
201 static void
202 attach_tx3904tmr_regs (struct hw *me,
203                       struct tx3904tmr *controller)
204 {
205   unsigned_word attach_address;
206   int attach_space;
207   unsigned attach_size;
208   reg_property_spec reg;
209
210   if (hw_find_property (me, "reg") == NULL)
211     hw_abort (me, "Missing \"reg\" property");
212
213   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
214     hw_abort (me, "\"reg\" property must contain one addr/size entry");
215
216   hw_unit_address_to_attach_address (hw_parent (me),
217                                      &reg.address,
218                                      &attach_space,
219                                      &attach_address,
220                                      me);
221   hw_unit_size_to_attach_size (hw_parent (me),
222                                &reg.size,
223                                &attach_size, me);
224
225   hw_attach_address (hw_parent (me), 0,
226                      attach_space, attach_address, attach_size,
227                      me);
228
229   if(hw_find_property(me, "clock") != NULL)
230     controller->clock_ticks = (unsigned_4) hw_find_integer_property(me, "clock");
231
232   if(hw_find_property(me, "ext") != NULL)
233     controller->ext_ticks = (unsigned_4) hw_find_integer_property(me, "ext");
234
235   controller->base_address = attach_address;
236 }
237
238
239 static void
240 tx3904tmr_finish (struct hw *me)
241 {
242   struct tx3904tmr *controller;
243
244   controller = HW_ZALLOC (me, struct tx3904tmr);
245   set_hw_data (me, controller);
246   set_hw_io_read_buffer (me, tx3904tmr_io_read_buffer);
247   set_hw_io_write_buffer (me, tx3904tmr_io_write_buffer);
248   set_hw_ports (me, tx3904tmr_ports);
249   set_hw_port_event (me, tx3904tmr_port_event);
250
251   /* Preset clock dividers */
252   controller->clock_ticks = 1;
253   controller->ext_ticks = 100;
254
255   /* Attach ourself to our parent bus */
256   attach_tx3904tmr_regs (me, controller);
257
258   /* Initialize to reset state */
259   controller->tcr = 
260     controller->itmr =
261     controller->ccdr =
262     controller->pmgr = 
263     controller->wtmr =
264     controller->tisr = 
265     controller->trr = 0;
266   controller->cpra = controller->cprb = 0x00FFFFFF;
267   controller->ff = 0;
268   controller->last_ticks = controller->roundoff_ticks = 0;
269   controller->event = NULL;
270 }
271
272
273
274 /* An event arrives on an interrupt port */
275
276 static void
277 tx3904tmr_port_event (struct hw *me,
278                      int my_port,
279                      struct hw *source,
280                      int source_port,
281                      int level)
282 {
283   struct tx3904tmr *controller = hw_data (me);
284
285   switch (my_port)
286     {
287     case RESET_PORT:
288       {
289         HW_TRACE ((me, "reset"));
290
291         /* preset flip-flop to FFI value */
292         controller->ff = GET_PMGR_FFI(controller);
293
294         controller->tcr = 
295           controller->itmr =
296           controller->ccdr =
297           controller->pmgr = 
298           controller->wtmr =
299           controller->tisr = 
300           controller->trr = 0;
301         controller->cpra = controller->cprb = 0x00FFFFFF;
302         controller->last_ticks = controller->roundoff_ticks = 0;
303         if(controller->event != NULL)
304           hw_event_queue_deschedule(me, controller->event);
305         controller->event = NULL;
306         break;
307       }
308
309     default:
310       hw_abort (me, "Event on unknown port %d", my_port);
311       break;
312     }
313 }
314
315
316 /* generic read/write */
317
318 static unsigned
319 tx3904tmr_io_read_buffer (struct hw *me,
320                          void *dest,
321                          int space,
322                          unsigned_word base,
323                          unsigned nr_bytes)
324 {
325   struct tx3904tmr *controller = hw_data (me);
326   unsigned byte;
327
328   HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
329   for (byte = 0; byte < nr_bytes; byte++)
330     {
331       address_word address = base + byte;
332       int reg_number = (address - controller->base_address) / 4;
333       int reg_offset = 3 - (address - controller->base_address) % 4;
334       unsigned_4 register_value; /* in target byte order */
335
336       /* fill in entire register_value word */
337       switch (reg_number)
338         {
339         case TCR_REG: register_value = controller->tcr; break;
340         case TISR_REG: register_value = controller->tisr; break;
341         case CPRA_REG: register_value = controller->cpra; break;
342         case CPRB_REG: register_value = controller->cprb; break;
343         case ITMR_REG: register_value = controller->itmr; break;
344         case CCDR_REG: register_value = controller->ccdr; break;
345         case PMGR_REG: register_value = controller->pmgr; break;
346         case WTMR_REG: register_value = controller->wtmr; break;
347         case TRR_REG: register_value = controller->trr; break;
348         default: register_value = 0;
349         }
350
351       /* write requested byte out */
352       memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1);
353     }
354
355   return nr_bytes;
356 }     
357
358
359
360 static unsigned
361 tx3904tmr_io_write_buffer (struct hw *me,
362                           const void *source,
363                           int space,
364                           unsigned_word base,
365                           unsigned nr_bytes)
366 {
367   struct tx3904tmr *controller = hw_data (me);
368   unsigned byte;
369
370   HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
371   for (byte = 0; byte < nr_bytes; byte++)
372     {
373       address_word address = base + byte;
374       unsigned_1 write_byte = ((const char*) source)[byte];
375       int reg_number = (address - controller->base_address) / 4;
376       int reg_offset = 3 - (address - controller->base_address) % 4;
377
378       /* fill in entire register_value word */
379       switch (reg_number)
380         {
381         case TCR_REG:
382           if(reg_offset == 0) /* first byte */
383             {
384               /* update register, but mask out NOP bits */
385               controller->tcr = (unsigned_4) (write_byte & 0xef);
386
387               /* Reset counter value if timer suspended and CRE is set. */
388               if(GET_TCR_TCE(controller) == 0 &&
389                  GET_TCR_CRE(controller) == 1)
390                 controller->trr = 0;
391             }
392           /* HW_TRACE ((me, "tcr: %08lx", (long) controller->tcr)); */
393           break;
394
395         case ITMR_REG:
396           if(reg_offset == 1) /* second byte */
397             {
398               SET_ITMR_TIIE(controller, write_byte & 0x80);
399             }
400           else if(reg_offset == 0) /* first byte */
401             {
402               SET_ITMR_TZCE(controller, write_byte & 0x01);
403             }
404           /* HW_TRACE ((me, "itmr: %08lx", (long) controller->itmr)); */
405           break;
406
407         case CCDR_REG:
408           if(reg_offset == 0) /* first byte */
409             {
410               controller->ccdr = write_byte & 0x07;
411             }
412           /* HW_TRACE ((me, "ccdr: %08lx", (long) controller->ccdr)); */
413           break;
414
415         case PMGR_REG:
416           if(reg_offset == 1) /* second byte */
417             {
418               SET_PMGR_TPIBE(controller, write_byte & 0x80);
419               SET_PMGR_TPIAE(controller, write_byte & 0x40);
420             }
421           else if(reg_offset == 0) /* first byte */
422             {
423               SET_PMGR_FFI(controller, write_byte & 0x01);
424             }
425           /* HW_TRACE ((me, "pmgr: %08lx", (long) controller->pmgr)); */
426           break;
427
428         case WTMR_REG:
429           if(reg_offset == 1) /* second byte */
430             {
431               SET_WTMR_TWIE(controller, write_byte & 0x80);
432             }
433           else if(reg_offset == 0) /* first byte */
434             {
435               SET_WTMR_WDIS(controller, write_byte & 0x80);
436               SET_WTMR_TWC(controller, write_byte & 0x01);
437             }
438           /* HW_TRACE ((me, "wtmr: %08lx", (long) controller->wtmr)); */
439           break;
440
441         case TISR_REG:
442           if(reg_offset == 0) /* first byte */
443             {
444               /* All bits must be zero in given byte, according to
445                  spec. */
446
447               /* Send an "interrupt off" event on the interrupt port */
448               if(controller->tisr != 0) /* any interrupts active? */
449                 {
450                   hw_port_event(me, INT_PORT, 0);                 
451                 }
452               
453               /* clear interrupt status register */
454               controller->tisr = 0;
455             }
456           /* HW_TRACE ((me, "tisr: %08lx", (long) controller->tisr)); */
457           break;
458
459         case CPRA_REG:
460           if(reg_offset < 3) /* first, second, or third byte */
461             {
462               MBLIT32(controller->cpra, (reg_offset*8)+7, (reg_offset*8), write_byte);
463             }
464           /* HW_TRACE ((me, "cpra: %08lx", (long) controller->cpra)); */
465           break;
466
467         case CPRB_REG:
468           if(reg_offset < 3) /* first, second, or third byte */
469             {
470               MBLIT32(controller->cprb, (reg_offset*8)+7, (reg_offset*8), write_byte);
471             }
472           /* HW_TRACE ((me, "cprb: %08lx", (long) controller->cprb)); */
473           break;
474
475         default: 
476           HW_TRACE ((me, "write to illegal register %d", reg_number));
477         }
478     } /* loop over bytes */
479
480   /* Schedule a timer event in near future, so we can increment or
481      stop the counter, to respond to register updates. */
482   hw_event_queue_schedule(me, 1, deliver_tx3904tmr_tick, NULL);
483
484   return nr_bytes;
485 }     
486
487
488
489 /* Deliver a clock tick to the counter. */
490 static void
491 deliver_tx3904tmr_tick (struct hw *me,
492                         void *data)
493 {
494   struct tx3904tmr *controller = hw_data (me);
495   SIM_DESC sd = hw_system (me);
496   signed_8 this_ticks = sim_events_time(sd);
497
498   signed_8 warp;
499   signed_8 divisor;
500   signed_8 quotient, remainder;
501
502   /* compute simulation ticks between last tick and this tick */
503   if(controller->last_ticks != 0)
504     warp = this_ticks - controller->last_ticks + controller->roundoff_ticks;
505   else
506     {
507       controller->last_ticks = this_ticks; /* initialize */
508       warp = controller->roundoff_ticks;
509     }
510
511   if(controller->event != NULL)
512     hw_event_queue_deschedule(me, controller->event);
513   controller->event = NULL;
514
515   /* Check whether the timer ticking is enabled at this moment.  This
516      largely a function of the TCE bit, but is also slightly
517      mode-dependent. */
518   switch((int) GET_TCR_TMODE(controller))
519     {
520     case 0: /* interval */
521       /* do not advance counter if TCE = 0 or if holding at count = CPRA */
522       if(GET_TCR_TCE(controller) == 0 ||
523          controller->trr == controller->cpra)
524         return;
525       break;
526
527     case 1: /* pulse generator */
528       /* do not advance counter if TCE = 0 */
529       if(GET_TCR_TCE(controller) == 0)
530         return;
531       break;
532
533     case 2: /* watchdog */
534       /* do not advance counter if TCE = 0 and WDIS = 1 */
535       if(GET_TCR_TCE(controller) == 0 &&
536          GET_WTMR_WDIS(controller) == 1)
537         return;
538       break;
539
540     case 3: /* disabled */
541       /* regardless of TCE, do not advance counter */
542       return;
543     }
544
545   /* In any of the above cases that return, a subsequent register
546      write will be needed to restart the timer.  A tick event is
547      scheduled by any register write, so it is more efficient not to
548      reschedule dummy events here. */
549
550
551   /* find appropriate divisor etc. */ 
552   if(GET_TCR_CCS(controller) == 0) /* internal system clock */
553     {
554       /* apply internal clock divider */
555       if(GET_TCR_CCDE(controller)) /* divisor circuit enabled? */
556         divisor = controller->clock_ticks * (1 << (1 + GET_CCDR_CDR(controller)));
557       else
558         divisor = controller->clock_ticks;
559     }
560   else
561     {
562       divisor = controller->ext_ticks;
563     }
564
565   /* how many times to increase counter? */
566   quotient = warp / divisor;
567   remainder = warp % divisor;
568
569   /* NOTE: If the event rescheduling code works properly, the quotient
570      should never be larger than 1.  That is, we should receive events
571      here at least as frequently as the simulated counter is supposed
572      to decrement.  So the remainder (-> roundoff_ticks) will slowly
573      accumulate, with the quotient == 0.  Once in a while, quotient
574      will equal 1. */
575
576   controller->roundoff_ticks = remainder;
577   controller->last_ticks = this_ticks;
578   while(quotient > 0) /* Is it time to increment counter? */
579     {
580       /* next 24-bit counter value */
581       unsigned_4 next_trr = (controller->trr + 1) % (1 << 24);
582       quotient --;
583       
584       switch((int) GET_TCR_TMODE(controller))
585         {
586         case 0: /* interval timer mode */
587           {
588             /* Current or next counter value matches CPRA value?  The
589                first case covers counter holding at maximum before
590                reset.  The second case covers normal counting
591                behavior. */
592             if(controller->trr == controller->cpra ||
593                next_trr == controller->cpra)
594               {
595                 /* likely hold CPRA value */
596                 if(controller->trr == controller->cpra)
597                   next_trr = controller->cpra;
598
599                 SET_TISR_TIIS(controller);
600
601                 /* Signal an interrupt if it is enabled with TIIE,
602                    and if we just arrived at CPRA.  Don't repeatedly
603                    interrupt if holding due to TZCE=0 */
604                 if(GET_ITMR_TIIE(controller) &&
605                    next_trr != controller->trr)
606                   {
607                     hw_port_event(me, INT_PORT, 1);
608                   }
609
610                 /* Reset counter? */
611                 if(GET_ITMR_TZCE(controller))
612                   {
613                     next_trr = 0;
614                   }
615               }
616           }
617         break;
618
619         case 1: /* pulse generator mode */
620           {
621             /* first trip point */
622             if(next_trr == controller->cpra)
623               {
624                 /* flip flip-flop & report */
625                 controller->ff ^= 1;
626                 hw_port_event(me, FF_PORT, controller->ff);
627                 SET_TISR_TPIAS(controller);
628
629                 /* signal interrupt */
630                 if(GET_PMGR_TPIAE(controller))
631                   {
632                     hw_port_event(me, INT_PORT, 1);
633                   }
634
635               }
636             /* second trip point */
637             else if(next_trr == controller->cprb)
638               {
639                 /* flip flip-flop & report */
640                 controller->ff ^= 1;
641                 hw_port_event(me, FF_PORT, controller->ff);
642                 SET_TISR_TPIBS(controller);
643
644                 /* signal interrupt */
645                 if(GET_PMGR_TPIBE(controller))
646                   {
647                     hw_port_event(me, INT_PORT, 1);
648                   }
649
650                 /* clear counter */
651                 next_trr = 0;
652               }
653           }
654         break;
655
656         case 2: /* watchdog timer mode */
657           {
658             /* watchdog timer expiry */
659             if(next_trr == controller->cpra)
660               {
661                 SET_TISR_TWIS(controller);
662
663                 /* signal interrupt */
664                 if(GET_WTMR_TWIE(controller))
665                   {
666                     hw_port_event(me, INT_PORT, 1);
667                   }
668
669                 /* clear counter */
670                 next_trr = 0;
671               }
672           }
673         break;
674
675         case 3: /* disabled */
676         default:
677           break;
678         }
679
680       /* update counter and report */
681       controller->trr = next_trr;
682       /* HW_TRACE ((me, "counter trr %ld tisr %lx",
683          (long) controller->trr, (long) controller->tisr)); */
684     } /* end quotient loop */
685
686   /* Reschedule a timer event in near future, so we can increment the
687      counter again.  Set the event about 75% of divisor time away, so
688      we will experience roughly 1.3 events per counter increment. */
689   controller->event = hw_event_queue_schedule(me, divisor*3/4, deliver_tx3904tmr_tick, NULL);
690 }
691
692
693
694
695 const struct hw_descriptor dv_tx3904tmr_descriptor[] = {
696   { "tx3904tmr", tx3904tmr_finish, },
697   { NULL },
698 };