1 /*
2    Copyright (C) 1998-2000 Scott Dattalo
3    Copyright (C) 2013-2017 Roy R. Rankin
4 
5 This file is part of the libgpsim library of gpsim
6 
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11 
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, see
19 <http://www.gnu.org/licenses/lgpl-2.1.html>.
20 */
21 
22 
23 #include <stdio.h>
24 #include <iostream>
25 #include <iomanip>
26 #include <string>
27 #include <assert.h>
28 
29 #include "14bit-processors.h"
30 #include "14bit-registers.h"
31 #include "14bit-tmrs.h"
32 
33 #include "breakpoints.h"
34 #include "gpsim_time.h"
35 #include "ioports.h"
36 #include "pic-processor.h"
37 #include "processor.h"
38 #include "stimuli.h"
39 #include "ui.h"
40 
41 //#include "xref.h"
42 #define PCLATH_MASK              0x1f
43 
44 //#define DEBUG
45 #if defined(DEBUG)
46 #define Dprintf(arg) {printf("0x%06" PRINTF_GINT64_MODIFIER "X %s() ", cycles.get(), __FUNCTION__); printf arg; }
47 #else
48 #define Dprintf(arg) {}
49 #endif
50 
51 // Debug OSCCON
52 //#define CDEBUG
53 #if defined(CDEBUG)
54 #define CDprintf(arg) {printf("0x%06" PRINTF_GINT64_MODIFIER "X %s() ", cycles.get(), __FUNCTION__); printf arg; }
55 #else
56 #define CDprintf(arg) {}
57 #endif
58 
59 pic_processor *temp_cpu;
60 // FIXME file_register::put_value has a useful feature...
61 
62 //
63 #if 0
64 //-----------------------------------------------------------
65 //  void file_register::put_value(unsigned int new_value)
66 //
67 //  put_value is used by the gui to change the contents of
68 // file registers. We could've let the gui use the normal
69 // 'put' member function to change the contents, however
70 // there are instances where 'put' has a cascading affect.
71 // For example, changing the value of an i/o port's tris
72 // could cause i/o pins to change states. In these cases,
73 // we'd like the gui to be notified of all of the cascaded
74 // changes. So rather than burden the real-time simulation
75 // with notifying the gui, I decided to create the 'put_value'
76 // function instead.
77 //   Since this is a virtual function, derived classes have
78 // the option to override the default behavior.
79 //
80 // inputs:
81 //   unsigned int new_value - The new value that's to be
82 //                            written to this register
83 // returns:
84 //   nothing
85 //
86 //-----------------------------------------------------------
87 
88 void file_register::put_value(unsigned int new_value)
89 {
90     // go ahead and use the regular put to write the data.
91     // note that this is a 'virtual' function. Consequently,
92     // all objects derived from a file_register should
93     // automagically be correctly updated.
94     put(new_value);
95 
96     // Even though we just wrote a value to this register,
97     // it's possible that the register did not get fully
98     // updated (e.g. porta on many pics has only 5 valid
99     // pins, so the upper three bits of a write are meaningless)
100     // So we should explicitly tell the gui (if it's
101     // present) to update its display.
102 
103     if (xref)
104     {
105         xref->update();
106 
107         if (cpu && address == cpu_pic->fsr->value)
108         {
109             if (cpu_pic->indf->xref)
110             {
111                 cpu_pic->indf->xref->update();
112             }
113         }
114     }
115 }
116 
117 #endif
118 
119 //--------------------------------------------------
120 // member functions for the BORCON class
121 // currently does not do anything
122 //--------------------------------------------------
123 //
BORCON(Processor * pCpu,const char * pName,const char * pDesc)124 BORCON::BORCON(Processor *pCpu, const char *pName, const char *pDesc)
125     : sfr_register(pCpu, pName, pDesc)
126 {
127 }
128 
129 
put(unsigned int new_value)130 void  BORCON::put(unsigned int new_value)
131 {
132     trace.raw(write_trace.get() | value.get());
133     value.put(new_value & 0x80);
134 }
135 
136 
put_value(unsigned int new_value)137 void  BORCON::put_value(unsigned int new_value)
138 {
139     put(new_value & 0x80);
140 }
141 
142 
143 //--------------------------------------------------
144 // member functions for the BSR class
145 //--------------------------------------------------
146 //
BSR(Processor * pCpu,const char * pName,const char * pDesc)147 BSR::BSR(Processor *pCpu, const char *pName, const char *pDesc)
148     : sfr_register(pCpu, pName, pDesc)
149 {
150 }
151 
152 
put(unsigned int new_value)153 void  BSR::put(unsigned int new_value)
154 {
155     trace.raw(write_trace.get() | value.get());
156     value.put(new_value & 0x01f);
157 
158     //value.put(new_value & 0x01f);
159     if (cpu_pic->base_isa() == _14BIT_E_PROCESSOR_)
160     {
161         cpu_pic->register_bank = &cpu_pic->registers[ value.get() << 7 ];
162 
163     }
164     else
165     {
166         cpu_pic->register_bank = &cpu_pic->registers[ value.get() << 8 ];
167     }
168 }
169 
170 
put_value(unsigned int new_value)171 void  BSR::put_value(unsigned int new_value)
172 {
173     put(new_value);
174     update();
175     cpu_pic->indf->update();
176 }
177 
178 
put(unsigned int new_value)179 void  IOCxF::put(unsigned int new_value)
180 {
181     unsigned int masked_value = new_value & mValidBits;
182     Dprintf((" %s value %x masked %x\n", name().c_str(), new_value, masked_value));
183     get_trace().raw(write_trace.get() | value.get());
184     value.put(masked_value);
185 
186     if (intcon)
187     {
188         ((INTCON_14_PIR *)intcon)->set_rbif(masked_value != 0);
189         ((INTCON_14_PIR *)intcon)->aocxf_val(this, masked_value);
190     }
191 }
192 
193 
194 // Adjust internal RC oscillator frequency as per 12f675/629
195 // Spec sheet does not give range so assume +/- 12.5% as per 16f88
196 // The fact that base_freq is not 0. indicates the RC oscillator is being used
197 // and thus an adjustment should be made.
198 //
199 // This will work for any number of adjustment bits in byte but must be left justified
200 // and 1000000 centre frequency and 11111111 highest frequency
put(unsigned int new_value)201 void  OSCCAL::put(unsigned int new_value)
202 {
203     int   adj = new_value & mValidBits;
204     trace.raw(write_trace.get() | value.get());
205     value.put(adj);
206 
207     if (base_freq > 0.0)
208     {
209         adj  = adj -  0x80;
210 
211         // A hook to honour configured frequency - if we're going to change it now
212         if (cpu_pic->get_frequency() > base_freq * 0.875 && base_freq * 1.125 > cpu_pic->get_frequency())
213         {
214             base_freq = cpu_pic->get_frequency();
215 
216             if (verbose)
217             {
218                 std::cout << "Adjusting base frequency for INTOSC calibration: " << base_freq << '\n';
219             }
220         }
221 
222         float tune = (1.0 + 0.125 * adj / 0x80) * base_freq;
223         cpu_pic->set_frequency(tune);
224 
225         if (verbose)
226         {
227             std::cout << "Calibrating INTOSC by " << adj << " to " << tune << '\n';
228         }
229     }
230 }
231 
232 
set_freq(float new_base_freq)233 void OSCCAL::set_freq(float new_base_freq)
234 {
235     base_freq = new_base_freq;
236     put(value.get());
237 }
238 
239 
put(unsigned int new_value)240 void  OSCTUNE::put(unsigned int new_value)
241 {
242     trace.raw(write_trace.get() | value.get());
243     value.put(new_value);
244     osccon->set_rc_frequency();
245 }
246 
247 
248 // Clock is stable
callback()249 void OSCCON::callback()
250 {
251     unsigned int new_value = value.get();
252 
253     if (future_cycle <= get_cycles().get())
254     {
255         future_cycle = 0;
256     }
257 
258     CDprintf(("OSCCON clock_state=%u\n", clock_state));
259 
260     switch (clock_state)
261     {
262     case OST:
263         CDprintf(("OSCCON switch clock\n"));
264 
265         if (has_iofs_bit)
266         {
267             new_value &= ~IOFS;
268 
269         }
270         else
271         {
272             new_value &= ~(HTS | LTS);
273         }
274 
275         new_value |= OSTS;
276         value.put(new_value);
277         clock_state = EXCSTABLE;
278         cpu_pic->set_RCfreq_active(false);
279         return;
280 
281     case LFINTOSC:
282         if (has_iofs_bit)
283         {
284             new_value |= IOFS;
285 
286         }
287         else
288         {
289             new_value &= ~HTS;
290             new_value |= LTS;
291         }
292 
293         value.put(new_value);
294         CDprintf(("OSCCON HF osccon=0x%x\n", value.get()));
295         return;
296 
297     case HFINTOSC:
298         if (!has_iofs_bit)
299         {
300             new_value &= ~LTS;
301         }
302 
303         new_value |= HTS;
304         value.put(new_value);
305         CDprintf(("OSCCON HF osccon=0x%x\n", value.get()));
306         return;
307 
308     case INTOSC:
309         new_value |= IOFS;
310         value.put(new_value);
311         return;
312 
313     case EXCSTABLE:
314         if (!has_iofs_bit)
315         {
316             new_value &= ~LTS;
317         }
318 
319         new_value &= ~HTS;
320         value.put(new_value);
321         return;
322 
323     default:
324         fprintf(stderr, "OSCCON::callback unexpexted clock state %u\n", clock_state);
325         return;
326     }
327 }
328 
329 
330 // Is internal RC clock selected?
internal_RC()331 bool OSCCON::internal_RC()
332 {
333     unsigned int scs = (value.get() & (SCS0 | SCS1)) & write_mask;
334     bool ret = false;
335 
336     if (scs == 0 && config_irc)
337     {
338         ret = true;
339 
340     }
341     else if ((SCS1 & write_mask) && scs == 2)  	// using SCS1 and SCS0
342     {
343         ret = true;
344 
345     }
346     else if (scs == 1)
347     {
348         ret = true;
349     }
350 
351     CDprintf(("OSCCON internal_RC ret %d osccon=0x%x\n", ret, value.get()));
352     return ret;
353 }
354 
355 
reset(RESET_TYPE r)356 void OSCCON::reset(RESET_TYPE r)
357 {
358     switch (r)
359     {
360     case POR_RESET:
361         value.put(por_value.data);
362         por_wake();
363         break;
364 
365     default:
366 
367         // Most registers simply retain their value across WDT resets.
368         if (wdtr_value.initialized())
369         {
370             putRV(wdtr_value);
371         }
372 
373         break;
374     }
375 }
376 
377 
sleep()378 void OSCCON::sleep()
379 {
380     is_sleeping = true;
381 }
382 
383 
wake()384 void OSCCON::wake()
385 {
386     if (!is_sleeping)
387     {
388         return;
389     }
390 
391     is_sleeping = false;
392     CDprintf(("OSCCON config_ieso %d int RC %d two_speed_clock=%d cpu=%s\n", config_ieso, internal_RC(), (config_xosc  && config_ieso), cpu_pic->name().c_str()));
393     por_wake();
394 }
395 
396 
por_wake()397 void OSCCON::por_wake()
398 {
399     bool two_speed_clock = config_xosc  && config_ieso;
400     unsigned int new_value = value.get();
401     CDprintf(("OSCCON config_xosc=%d config_ieso=%d\n", config_xosc, config_ieso));
402     CDprintf(("OSCCON POR two_speed_clock=%d f=%4.1e osccon=0x%x por_value=0x%x\n", two_speed_clock, cpu_pic->get_frequency(), new_value, por_value.data));
403 
404     if (future_cycle)
405     {
406         get_cycles().clear_break(future_cycle);
407         future_cycle = 0;
408     }
409 
410     // internal RC osc
411     if (internal_RC())
412     {
413         if (has_iofs_bit)
414         {
415             new_value &= ~IOFS;
416             clock_state = INTOSC;
417 
418         }
419         else if (new_value & (IRCF0 | IRCF1 | IRCF2))
420         {
421             new_value &= ~(HTS | LTS);
422             clock_state = HFINTOSC;
423 
424         }
425         else
426         {
427             new_value &= ~(HTS | LTS);
428             clock_state = LFINTOSC;
429         }
430 
431         new_value |= OSTS;
432         value.put(new_value);
433         CDprintf(("OSCCON internal RC clock_state %u osccon %x\n", clock_state, new_value));
434 
435         //RRR	set_rc_frequency();
436         if (future_cycle)
437         {
438             get_cycles().clear_break(future_cycle);
439         }
440 
441         future_cycle = get_cycles().get() + irc_por_time();
442         get_cycles().set_break(future_cycle, this);
443         return;
444     }
445 
446     if (two_speed_clock)
447     {
448         if (has_iofs_bit)
449         {
450             new_value &= ~(IOFS | OSTS);
451 
452         }
453         else
454         {
455             new_value &= ~(HTS | LTS | OSTS);
456         }
457 
458         value.put(new_value);
459         set_rc_frequency(true);
460         CDprintf(("OSCCON  2 speed, set osccon 0x%x \n", value.get()));
461         clock_state = OST;
462         future_cycle = 1024 + get_cycles().get();
463         get_cycles().set_break(future_cycle, this);
464         return;
465     }
466 }
467 
468 
469 /*
470  *
471  *
472  */
set_rc_frequency(bool override)473 bool OSCCON::set_rc_frequency(bool override)
474 {
475     double base_frequency = 31.e3;
476     unsigned int old_clock_state = clock_state;
477     unsigned int new_IRCF = (value.get() & (IRCF0 | IRCF1 | IRCF2)) >> 4;
478 
479     if (!internal_RC() && !override)
480     {
481         return false;
482     }
483 
484     switch (new_IRCF)
485     {
486     case 0:
487         base_frequency = 31.e3;
488         break;
489 
490     case 1:
491         base_frequency = 125e3;
492         break;
493 
494     case 2:
495         base_frequency = 250e3;
496         break;
497 
498     case 3:
499         base_frequency = 500e3;
500         break;
501 
502     case 4:
503         base_frequency = 1e6;
504         break;
505 
506     case 5:
507         base_frequency = 2e6;
508         break;
509 
510     case 6:
511         base_frequency = 4e6;
512         break;
513 
514     case 7:
515         base_frequency = 8e6;
516         break;
517     }
518 
519     if (osctune)
520     {
521         int tune;
522         unsigned int osctune_value = osctune->value.get();
523         tune = osctune_value & (OSCTUNE::TUN5 - 1);
524         tune = (OSCTUNE::TUN5 & osctune_value) ? -tune : tune;
525         base_frequency *= 1.0 + 0.125 * tune / 31.0;
526     }
527 
528     cpu_pic->set_RCfreq_active(true);
529     cpu_pic->set_frequency_rc(base_frequency);
530     clock_state = new_IRCF ? HFINTOSC : LFINTOSC;
531 
532     if (old_clock_state != clock_state)
533     {
534         if ((old_clock_state == LFINTOSC) && clock_state != LFINTOSC)
535         {
536             if (has_iofs_bit)
537             {
538                 value.put(value.get() & ~(IOFS));
539 
540             }
541             else
542             {
543                 value.put(value.get() & ~(LTS | HTS));
544             }
545 
546             if (future_cycle)
547             {
548                 get_cycles().clear_break(future_cycle);
549             }
550 
551             future_cycle = get_cycles().get() + irc_lh_time();
552             get_cycles().set_break(future_cycle, this);
553             CDprintf(("OSCCON future_cycle %" PRINTF_GINT64_MODIFIER "d now %" PRINTF_GINT64_MODIFIER "d\n", future_cycle, get_cycles().get()));
554 
555         }
556         else
557         {
558             /*RRR
559             	    unsigned int current = value.get();
560             	    if (clock_state == HFINTOSC)
561             	    {
562             		if (has_iofs_bit) current &= ~LTS;
563             		current |= HTS;
564             		value.put(current);
565             	    }
566             */
567             callback();
568         }
569     }
570 
571     CDprintf(("OSCCON new_ircf %u  %4.1f \n", new_IRCF, cpu_pic->get_frequency()));
572 
573     if ((bool)verbose)
574     {
575         std::cout << "set_rc_frequency() : osccon=" << std::hex << value.get();
576 
577         if (osctune)
578         {
579             std::cout << " osctune=" << osctune->value.get();
580         }
581 
582         std::cout << " new frequency=" << base_frequency << '\n';
583     }
584 
585     return true;
586 }
587 
588 
put(unsigned int new_value)589 void  OSCCON::put(unsigned int new_value)
590 {
591     unsigned int org_value = value.get();
592     new_value = (new_value & write_mask) | (org_value & ~write_mask);
593     value.put(new_value);
594     unsigned int diff = (new_value ^ org_value);
595     trace.raw(write_trace.get() | org_value);
596     value.put(new_value);
597     CDprintf(("OSCCON org_value=0x%02x new_value=0x%02x diff=0x%02x state %u\n",
598               org_value, new_value, diff, clock_state));
599 
600     if (diff == 0)
601     {
602         return;
603     }
604 
605     if (internal_RC())
606     {
607 #ifdef CDEBUG
608         unsigned int old_clock_state = clock_state;
609 #endif
610 
611         if ((diff & (IRCF0 | IRCF1 | IRCF2)))   // freq change
612         {
613             set_rc_frequency();
614             CDprintf(("OSCCON change of IRCF old_clock %u new_clock %u\n", old_clock_state, clock_state));
615         }
616 
617         // switching to intrc
618         else if (diff & (SCS0 | SCS1))   // still OK if SCS1 is non-writtabe LTS
619         {
620             set_rc_frequency(true);
621             CDprintf(("OSCCON diff 0x%x old_clock_state %u clock_state %u\n", (diff & (SCS0 | SCS1)), old_clock_state, clock_state));
622         }
623 
624     }
625     else     // not Internal RC clock
626     {
627         clock_state = EXCSTABLE;
628         cpu_pic->set_RCfreq_active(false);
629         callback();
630         CDprintf(("OSCCON not RC osccon=0x%x\n", new_value));
631     }
632 }
633 
634 
635 // Time required for stable clock after transition between high and low
636 // irc frequencies
irc_lh_time()637 guint64 OSCCON::irc_lh_time()
638 {
639     guint64 delay = (get_cycles().instruction_cps() * 1e-6) + 1;
640     return delay;
641 }
642 
643 
644 // Time required for stable irc clock after POR
irc_por_time()645 guint64 OSCCON::irc_por_time()
646 {
647     return (guint64) 2;
648 }
649 
650 
irc_lh_time()651 guint64 OSCCON_1::irc_lh_time()
652 {
653     guint64 delay = get_cycles().instruction_cps() * 4e-3;
654     CDprintf(("OSCCON_1 LH irc time 4ms %" PRINTF_GINT64_MODIFIER "d cycles\n", delay));
655     return delay;
656 }
657 
658 
659 // Time required for stable irc clock after POR (4 ms)
irc_por_time()660 guint64 OSCCON_1::irc_por_time()
661 {
662     guint64 delay = get_cycles().instruction_cps() * 4e-3;
663     CDprintf(("OSCCON_1 POR irc time 4ms %" PRINTF_GINT64_MODIFIER "d cycles\n", delay));
664     return delay;
665 }
666 
667 
668 // Clock is stable
callback()669 void OSCCON_2::callback()
670 {
671     unsigned int add_bits = 0;
672     unsigned int val;
673     future_cycle = 0;
674 
675     if (!oscstat)
676     {
677         return;
678     }
679 
680     val = oscstat->value.get();
681     CDprintf(("OSCCON_2 oscstat = 0x%x\n", val));
682 
683     if (clock_state & PLL)
684     {
685         add_bits = OSCSTAT::PLLR;
686     }
687 
688     switch (clock_state & ~PLL)
689     {
690     case OST:
691         add_bits = OSCSTAT::OSTS;
692         cpu_pic->set_RCfreq_active(false);
693         break;
694 
695     case LFINTOSC:
696         add_bits = OSCSTAT::LFIOFR;
697         val &= ~(OSCSTAT::HFIOFL | OSCSTAT::HFIOFR  | OSCSTAT::HFIOFS | OSCSTAT::MFIOFR);
698         break;
699 
700     case MFINTOSC:
701         add_bits = OSCSTAT::MFIOFR;
702         val &= ~(OSCSTAT::HFIOFL | OSCSTAT::HFIOFR  | OSCSTAT::HFIOFS | OSCSTAT::LFIOFR);
703         break;
704 
705     case HFINTOSC:
706         add_bits = OSCSTAT::HFIOFL | OSCSTAT::HFIOFR  | OSCSTAT::HFIOFS;
707         val &= ~(OSCSTAT::MFIOFR | OSCSTAT::LFIOFR);
708         break;
709 
710     case T1OSC:
711         break;
712     }
713 
714     val |= add_bits;
715     oscstat->value.put(val);
716 }
717 
718 
set_rc_frequency(bool override)719 bool OSCCON_2::set_rc_frequency(bool override)
720 {
721     double base_frequency = 31.25e3;
722     unsigned int sys_clock = value.get() & (SCS0 | SCS1);
723     bool osccon_pplx4 = value.get() & SPLLEN;
724     bool config_pplx4 = cpu_pic->get_pplx4_osc();
725     CDprintf(("OSCCON_2 new_IRCF 0x%x\n", (value.get() & (IRCF0 | IRCF1 | IRCF2 | IRCF3)) >> 3));
726 
727     if ((sys_clock == 0) && !config_irc)   // Not internal oscillator
728     {
729         if (!config_xosc)   // always run at full speed
730         {
731             unsigned int oscstat_reg = (oscstat->value.get() & 0x1f);
732             oscstat->value.put(oscstat_reg | OSCSTAT::OSTS);
733             clock_state = EC;
734 
735         }
736         else if (config_ieso)     // internal/external switchover
737         {
738             clock_state = OST;
739         }
740     }
741 
742     if ((osccon_pplx4 && !config_pplx4) && sys_clock == 0)
743     {
744         clock_state |= PLL;
745         return true;
746     }
747 
748     if (!cpu_pic->get_int_osc() && (sys_clock == 0) && !override)
749     {
750         return false;
751     }
752 
753     if (sys_clock == 1)   // T1OSC
754     {
755         base_frequency = 32.e3;
756         clock_state = T1OSC;
757 
758     }
759     else if (sys_clock > 1 || config_irc || override)
760     {
761         unsigned int new_IRCF = (value.get() & (IRCF0 | IRCF1 | IRCF2 | IRCF3)) >> 3;
762 
763         switch (new_IRCF)
764         {
765         case 0:
766         case 1:
767             base_frequency = 30.e3;
768             clock_state = LFINTOSC;
769             break;
770 
771         case 2:
772             clock_state = MFINTOSC;
773             base_frequency = 31.25e3;
774             break;
775 
776         case 3:
777             clock_state = HFINTOSC;
778             base_frequency = 31.25e3;
779             break;
780 
781         case 4:
782             clock_state = HFINTOSC;
783             base_frequency = 62.5e3;
784             break;
785 
786         case 5:
787             clock_state = HFINTOSC;
788             base_frequency = 125e3;
789             break;
790 
791         case 6:
792             clock_state = HFINTOSC;
793             base_frequency = 250e3;
794             break;
795 
796         case 7:
797             clock_state = HFINTOSC;
798             base_frequency = 500e3;
799             break;
800 
801         case 8:
802             clock_state = HFINTOSC;
803             base_frequency = 125e3;
804             break;
805 
806         case 9:
807             clock_state = HFINTOSC;
808             base_frequency = 250e3;
809             break;
810 
811         case 10:
812             clock_state = HFINTOSC;
813             base_frequency = 500e3;
814             break;
815 
816         case 11:
817             clock_state = HFINTOSC;
818             base_frequency = 1e6;
819             break;
820 
821         case 12:
822             clock_state = HFINTOSC;
823             base_frequency = 2e6;
824             break;
825 
826         case 13:
827             clock_state = HFINTOSC;
828             base_frequency = 4e6;
829             break;
830 
831         case 14:
832 
833             // The treatment for PPL based on Fig 5-1 of P12f1822 ref manual
834             if (osccon_pplx4 || config_pplx4)
835             {
836                 clock_state = PLL;
837                 base_frequency = 32e6;
838 
839             }
840             else
841             {
842                 clock_state = HFINTOSC;
843                 base_frequency = 8e6;
844             }
845 
846             break;
847 
848         case 15:
849             clock_state = HFINTOSC;
850             base_frequency = 16e6;
851             break;
852         }
853     }
854 
855     if (osctune)
856     {
857         int tune;
858         unsigned int osctune_value = osctune->value.get();
859         tune = osctune_value & (OSCTUNE::TUN5 - 1);
860         tune = (OSCTUNE::TUN5 & osctune_value) ? -tune : tune;
861         base_frequency *= 1.0 + 0.125 * tune / 31.0;
862     }
863 
864     cpu_pic->set_RCfreq_active(true);
865     cpu_pic->set_frequency_rc(base_frequency);
866 
867     if ((bool)verbose)
868     {
869         std::cout << "set_rc_frequency() : osccon=" << std::hex << value.get();
870 
871         if (osctune)
872         {
873             std::cout << " osctune=" << osctune->value.get();
874         }
875 
876         std::cout << " new frequency=" << base_frequency << '\n';
877     }
878 
879     return true;
880 }
881 
882 
por_wake()883 void OSCCON_2::por_wake()
884 {
885     bool two_speed_clock = config_xosc  && config_ieso;
886     CDprintf(("OSCCON_2 two_speed_clock=%d f=%4.1e\n", two_speed_clock, cpu_pic->get_frequency()));
887 
888     if (future_cycle)
889     {
890         get_cycles().clear_break(future_cycle);
891         future_cycle = 0;
892         clock_state = UNDEF;
893     }
894 
895     // internal RC osc
896     if (internal_RC())
897     {
898         CDprintf(("OSCCON_2 internal RC clock_state %u\n", clock_state));
899         oscstat->value.put(OSCSTAT::OSTS);
900         set_rc_frequency();
901         future_cycle = get_cycles().get() + irc_por_time();
902         get_cycles().set_break(future_cycle, this);
903         return;
904     }
905 
906     if (two_speed_clock)
907     {
908         bool config_pplx4 = cpu_pic->get_pplx4_osc();
909         oscstat->value.put(0);
910         set_rc_frequency(true);
911         clock_state = OST;
912 
913         if (config_pplx4)
914         {
915             clock_state |= PLL;
916         }
917 
918         CDprintf(("OSCCON_2  2 speed, set osccon 0x%x \n", value.get()));
919         future_cycle = 1024 + get_cycles().get();
920         get_cycles().set_break(future_cycle, this);
921         return;
922     }
923 
924     oscstat->value.put(0);
925 }
926 
927 
put_value(unsigned int new_value)928 void  OSCCON_2::put_value(unsigned int new_value)
929 {
930     CDprintf(("OSCCON_2 0x%x\n", new_value));
931     value.put(new_value);
932 }
933 
934 
put(unsigned int new_value)935 void  OSCCON_2::put(unsigned int new_value)
936 {
937     unsigned int old_value = value.get();
938     new_value = (new_value & write_mask);
939     unsigned int oscstat_reg = 0;
940     unsigned int oscstat_new = 0;
941     trace.raw(write_trace.get() | value.get());
942     value.put(new_value);
943 
944     if (old_value == new_value)
945     {
946         return;
947     }
948 
949     assert(oscstat);
950     oscstat_reg = oscstat->value.get();
951     oscstat_new = oscstat_reg;
952 
953     if (((new_value & (SCS0 | SCS1)) == 0) && !cpu_pic->get_int_osc())
954     {
955         oscstat_new |= OSCSTAT::OSTS;
956 
957     }
958     else
959     {
960         oscstat_new &= ~OSCSTAT::OSTS;
961     }
962 
963     CDprintf(("OSCCON_2 0x%x\n", new_value));
964 
965     if (set_rc_frequency())   // using internal RC Oscillator
966     {
967         set_callback();
968     }
969 }
970 
971 
set_callback()972 void OSCCON_2::set_callback()
973 {
974     unsigned int oscstat_reg = oscstat->value.get();;
975     unsigned int oscstat_new = oscstat_reg;
976     guint64 settle = 0;
977     CDprintf(("OSCCON_2 clock_state 0x%x\n", clock_state));
978 
979     switch (clock_state & ~ PLL)
980     {
981     case LFINTOSC:
982         oscstat_new &= ~(OSCSTAT::OSTS | OSCSTAT::PLLR | OSCSTAT::T1OSCR);
983         settle = get_cycles().get() + 2;
984         break;
985 
986     case MFINTOSC:
987         oscstat_new &= ~(OSCSTAT::OSTS | OSCSTAT::PLLR | OSCSTAT::T1OSCR);
988         settle = get_cycles().get(2e-6); // 2us settle time
989         break;
990 
991     case HFINTOSC:
992         oscstat_new &= ~(OSCSTAT::OSTS | OSCSTAT::PLLR | OSCSTAT::T1OSCR);
993         settle = get_cycles().get(2e-6); // 2us settle time
994         CDprintf(("OSCCON_2 settle %" PRINTF_GINT64_MODIFIER "d\n", settle));
995         break;
996 
997     case T1OSC:
998         settle = get_cycles().get() + 1024 / 4;
999         break;
1000     }
1001 
1002     if ((clock_state & PLL) && (oscstat_reg & OSCSTAT::PLLR) == 0)
1003     {
1004         settle = get_cycles().get(2e-3);  // 2ms
1005     }
1006 
1007     if (settle)
1008     {
1009         settle += get_cycles().get();
1010 
1011         if (future_cycle > get_cycles().get())
1012         {
1013             get_cycles().clear_break(future_cycle);
1014         }
1015 
1016         get_cycles().set_break(settle, this);
1017         future_cycle = settle;
1018     }
1019 
1020     if (oscstat && (oscstat_new != oscstat_reg))
1021     {
1022         oscstat->put(oscstat_new);
1023     }
1024 }
1025 
1026 
put(unsigned int new_value)1027 void OSCCON2::put(unsigned int new_value)
1028 {
1029     trace.raw(write_trace.get() | value.get());
1030     new_value = (new_value & write_mask) | (new_value & ~write_mask);
1031     value.put(new_value);
1032     assert(osccon);
1033     osccon->set_rc_frequency();
1034 }
1035 
1036 
callback()1037 void OSCCON_HS::callback()
1038 {
1039     assert(osccon2);
1040     unsigned int val_osccon2 = osccon2->value.get();
1041     unsigned int val_osccon = value.get();
1042 
1043     if (future_cycle <= get_cycles().get())
1044     {
1045         future_cycle = 0;
1046     }
1047 
1048     CDprintf(("OSCCON_HS clock_state=%u osccon=0x%x osccon2=0x%x\n", clock_state, val_osccon, val_osccon2));
1049 
1050     switch (clock_state)
1051     {
1052     case OST:
1053         val_osccon &= ~ HFIOFS;
1054         val_osccon |= OSTS;
1055         val_osccon2 &= ~(OSCCON2::LFIOFS | OSCCON2::MFIOFS);
1056         cpu_pic->set_RCfreq_active(false);
1057         clock_state = EXCSTABLE;
1058         break;
1059 
1060     case LFINTOSC:
1061         val_osccon &= ~HFIOFS;
1062         val_osccon2 &= ~OSCCON2::MFIOFS;
1063         val_osccon2 |= OSCCON2::LFIOFS;
1064         break;
1065 
1066     case MFINTOSC:
1067         val_osccon &= ~HFIOFS;
1068         val_osccon2 &= ~OSCCON2::LFIOFS;
1069         val_osccon2 |= OSCCON2::MFIOFS;
1070         break;
1071 
1072     case HFINTOSC:
1073         val_osccon |= HFIOFS;
1074         val_osccon2 &= ~(OSCCON2::LFIOFS | OSCCON2::MFIOFS);
1075         break;
1076 
1077     case T1OSC:
1078         break;
1079 
1080     case EXCSTABLE:
1081         val_osccon &= ~HFIOFS;
1082         val_osccon |= OSTS;
1083         val_osccon2 &= ~(OSCCON2::LFIOFS | OSCCON2::MFIOFS);
1084         break;
1085     }
1086 
1087     value.put(val_osccon);
1088     CDprintf(("OSCCON_HS osccon 0x%x val_osccon 0x%x\n", value.get(), val_osccon));
1089     osccon2->value.put(val_osccon2);
1090 }
1091 
1092 
set_rc_frequency(bool override)1093 bool OSCCON_HS::set_rc_frequency(bool override)
1094 {
1095     double base_frequency = 31.e3;
1096     bool config_pplx4 = cpu_pic->get_pplx4_osc();
1097     bool osccon_pplx4 = (osctune) ? osctune->value.get() & OSCTUNE::PLLEN : false;
1098     bool intsrc	    = (osctune) ? osctune->value.get() & OSCTUNE::INTSRC : false;
1099     bool mfiosel	    = (osccon2) ? osccon2->value.get() & OSCCON2::MFIOSEL : false;
1100     unsigned int old_clock_state = clock_state;
1101     CDprintf(("OSCCON_HS override=%d int_osc=%d osccon=0x%x\n", override, cpu_pic->get_int_osc(), value.get()));
1102 
1103     if (!cpu_pic->get_int_osc() && !(value.get() & SCS1) && !override)
1104     {
1105         return false;
1106     }
1107 
1108     unsigned int new_IRCF = (value.get() & (IRCF0 | IRCF1 | IRCF2)) >> 4;
1109 
1110     switch (new_IRCF)
1111     {
1112     case 0:
1113         base_frequency = 31.e3;
1114 
1115         if (mfiosel)
1116         {
1117             clock_state = intsrc ? MFINTOSC : LFINTOSC;
1118 
1119         }
1120         else
1121         {
1122             clock_state = intsrc ? HFINTOSC : LFINTOSC;
1123         }
1124 
1125         break;
1126 
1127     case 1:
1128         clock_state = mfiosel ? MFINTOSC : HFINTOSC;
1129         base_frequency = 125e3;
1130         break;
1131 
1132     case 2:
1133         clock_state = mfiosel ? MFINTOSC : HFINTOSC;
1134         base_frequency = 250e3;
1135         break;
1136 
1137     case 3:
1138         clock_state = HFINTOSC;
1139         base_frequency = 1e6;
1140         break;
1141 
1142     case 4:
1143         clock_state = HFINTOSC;
1144         base_frequency = 2e6;
1145         break;
1146 
1147     case 5:
1148         clock_state = HFINTOSC;
1149         base_frequency = 4e6;
1150         break;
1151 
1152     case 6:
1153         clock_state = HFINTOSC;
1154         base_frequency = 8e6;
1155         break;
1156 
1157     case 7:
1158         clock_state = HFINTOSC;
1159         base_frequency = 16e6;
1160         break;
1161     }
1162 
1163     if ((new_IRCF >= minValPLL) && (osccon_pplx4 || config_pplx4))
1164     {
1165         base_frequency *= 4;
1166     }
1167 
1168     if (osctune)
1169     {
1170         int tune;
1171         unsigned int osctune_value = osctune->value.get();
1172         tune = osctune_value & (OSCTUNE::TUN5 - 1);
1173         tune = (OSCTUNE::TUN5 & osctune_value) ? -tune : tune;
1174         base_frequency *= 1.0 + 0.125 * tune / 31.0;
1175     }
1176 
1177     cpu_pic->set_frequency_rc(base_frequency);
1178 
1179     if (cpu_pic->get_int_osc() || (value.get() & SCS1))
1180     {
1181         CDprintf(("OSCCON_HS clock_state %u->%u f=%.1e osccon=0x%x\n", old_clock_state, clock_state, base_frequency, value.get()));
1182         cpu_pic->set_RCfreq_active(true);
1183 
1184         if (old_clock_state != clock_state)
1185         {
1186             if ((old_clock_state == LFINTOSC) && clock_state != LFINTOSC)
1187             {
1188                 if (future_cycle)
1189                 {
1190                     get_cycles().clear_break(future_cycle);
1191                 }
1192 
1193                 future_cycle = get_cycles().get() + irc_lh_time();
1194                 get_cycles().set_break(future_cycle, this);
1195                 CDprintf(("OSCCON_HS future_cycle %" PRINTF_GINT64_MODIFIER "d now %" PRINTF_GINT64_MODIFIER "d\n", future_cycle, get_cycles().get()));
1196 
1197             }
1198             else
1199             {
1200                 callback();
1201             }
1202         }
1203     }
1204 
1205     if ((bool)verbose)
1206     {
1207         std::cout << "set_rc_frequency() : osccon=" << std::hex << value.get();
1208 
1209         if (osctune)
1210         {
1211             std::cout << " osctune=" << osctune->value.get();
1212         }
1213 
1214         std::cout << " new frequency=" << base_frequency << '\n';
1215     }
1216 
1217     return true;
1218 }
1219 
1220 
1221 // Is internal RC clock selected?
internal_RC()1222 bool OSCCON_HS::internal_RC()
1223 {
1224     bool ret = false;
1225 
1226     if ((value.get() & SCS1) || config_irc)
1227     {
1228         ret = true;
1229     }
1230 
1231     return ret;
1232 }
1233 
1234 
por_wake()1235 void OSCCON_HS::por_wake()
1236 {
1237     bool two_speed_clock = config_xosc  && config_ieso;
1238     unsigned int val_osccon2 = osccon2->value.get();
1239     unsigned int val_osccon = value.get();
1240     CDprintf(("OSCCON_HS config_xosc=%d config_ieso=%d\n", config_xosc, config_ieso));
1241     CDprintf(("OSCCON_HS POR two_speed_clock=%d f=%4.1e osccon=0x%x por_value=0x%x\n", two_speed_clock, cpu_pic->get_frequency(), val_osccon, por_value.data));
1242 
1243     if (future_cycle)
1244     {
1245         get_cycles().clear_break(future_cycle);
1246         future_cycle = 0;
1247     }
1248 
1249     // internal RC osc
1250     if (internal_RC())
1251     {
1252         CDprintf(("OSCCON_HS internal RC clock_state %u osccon %x osccon2 %x\n", clock_state, val_osccon, val_osccon2));
1253         set_rc_frequency();
1254 
1255         if (future_cycle)
1256         {
1257             get_cycles().clear_break(future_cycle);
1258         }
1259 
1260         future_cycle = get_cycles().get() + irc_por_time();
1261         get_cycles().set_break(future_cycle, this);
1262         return;
1263     }
1264 
1265     if (two_speed_clock)
1266     {
1267         val_osccon &= ~(HFIOFS | OSTS);
1268         val_osccon2 &= ~(OSCCON2::LFIOFS | OSCCON2::MFIOFS);
1269         value.put(val_osccon);
1270         osccon2->value.put(val_osccon2);
1271         set_rc_frequency(true);
1272         cpu_pic->set_RCfreq_active(true);
1273         CDprintf(("OSCCON_HS 2 speed, set osccon 0x%x \n", value.get()));
1274 
1275         if (future_cycle)
1276         {
1277             get_cycles().clear_break(future_cycle);
1278         }
1279 
1280         clock_state = OST;
1281         future_cycle = 1024 + get_cycles().get();
1282         get_cycles().set_break(future_cycle, this);
1283         return;
1284     }
1285 }
1286 
1287 
put(unsigned int new_value)1288 void  OSCCON_HS2::put(unsigned int new_value)
1289 {
1290     unsigned int org_value = value.get();
1291     new_value = (new_value & write_mask) | (org_value & ~write_mask);
1292     value.put(new_value);
1293     unsigned int diff = (new_value ^ org_value);
1294     trace.raw(write_trace.get() | org_value);
1295     value.put(new_value);
1296     CDprintf(("OSCCON org_value=0x%02x new_value=0x%02x diff=0x%02x state %u\n",
1297               org_value, new_value, diff, clock_state));
1298 
1299     if (diff == 0)
1300     {
1301         return;
1302     }
1303 
1304     if (internal_RC())
1305     {
1306 #ifdef CDEBUG
1307         unsigned int old_clock_state = clock_state;
1308 #endif
1309 
1310         if ((diff & (IRCF0 | IRCF1 | IRCF2)))   // freq change
1311         {
1312             set_rc_frequency();
1313             CDprintf(("OSCCON_HS2 change of IRCF old_clock %u new_clock %u\n", old_clock_state, clock_state));
1314         }
1315     }
1316 }
1317 
1318 
set_rc_frequency(bool override)1319 bool OSCCON_HS2::set_rc_frequency(bool override)
1320 {
1321     double base_frequency = 31.e3;
1322     unsigned int old_clock_state = clock_state;
1323     CDprintf(("OSCCON_HS2 override=%d int_osc=%d osccon=0x%x\n", override, cpu_pic->get_int_osc(), value.get()));
1324 
1325     if (!cpu_pic->get_int_osc()  && !override)
1326     {
1327         return false;
1328     }
1329 
1330     unsigned int new_IRCF = (value.get() & (IRCF0 | IRCF1 | IRCF2)) >> 4;
1331 
1332     switch (new_IRCF)
1333     {
1334     case 0:
1335         base_frequency = 31.e3;
1336         clock_state = LFINTOSC;
1337         break;
1338 
1339     case 1:
1340         clock_state = HFINTOSC;
1341         base_frequency = 250e3;
1342         break;
1343 
1344     case 2:
1345         clock_state = HFINTOSC;
1346         base_frequency = 500e3;
1347         break;
1348 
1349     case 3:
1350         clock_state = HFINTOSC;
1351         base_frequency = 1e6;
1352         break;
1353 
1354     case 4:
1355         clock_state = HFINTOSC;
1356         base_frequency = 2e6;
1357         break;
1358 
1359     case 5:
1360         clock_state = HFINTOSC;
1361         base_frequency = 4e6;
1362         break;
1363 
1364     case 6:
1365         clock_state = HFINTOSC;
1366         base_frequency = 8e6;
1367         break;
1368 
1369     case 7:
1370         clock_state = HFINTOSC;
1371         base_frequency = 16e6;
1372         break;
1373     }
1374 
1375     cpu_pic->set_frequency_rc(base_frequency);
1376 
1377     if (cpu_pic->get_int_osc())
1378     {
1379         CDprintf(("OSCCON_HS2 clock_state %u->%u f=%.1e osccon=0x%x\n", old_clock_state, clock_state, base_frequency, value.get()));
1380         cpu_pic->set_RCfreq_active(true);
1381 
1382         if (old_clock_state != clock_state)
1383         {
1384             if ((old_clock_state == LFINTOSC) && clock_state != LFINTOSC)
1385             {
1386                 if (future_cycle)
1387                 {
1388                     get_cycles().clear_break(future_cycle);
1389                 }
1390 
1391                 future_cycle = get_cycles().get() + irc_lh_time();
1392                 get_cycles().set_break(future_cycle, this);
1393                 CDprintf(("OSCCON_HS2 future_cycle %" PRINTF_GINT64_MODIFIER "d now %" PRINTF_GINT64_MODIFIER "d\n", future_cycle, get_cycles().get()));
1394 
1395             }
1396             else
1397             {
1398                 callback();
1399             }
1400         }
1401     }
1402 
1403     if ((bool)verbose)
1404     {
1405         std::cout << "set_rc_frequency() : osccon=" << std::hex << value.get();
1406 
1407         if (osctune)
1408         {
1409             std::cout << " osctune=" << osctune->value.get();
1410         }
1411 
1412         std::cout << " new frequency=" << base_frequency << '\n';
1413     }
1414 
1415     return true;
1416 }
1417 
1418 
1419 // Is internal RC clock selected?
internal_RC()1420 bool OSCCON_HS2::internal_RC()
1421 {
1422     return cpu_pic->get_int_osc();
1423 }
1424 
1425 
callback()1426 void OSCCON_HS2::callback()
1427 {
1428     unsigned int val_osccon = value.get() & write_mask;
1429 
1430     if (future_cycle <= get_cycles().get())
1431     {
1432         future_cycle = 0;
1433     }
1434 
1435     CDprintf(("OSCCON_HS2 clock_state=%u osccon=0x%x val_osccon=0x%x\n", clock_state, value.get(), val_osccon));
1436 
1437     switch (clock_state)
1438     {
1439     case LFINTOSC:
1440         val_osccon |= LFIOFR;
1441         break;
1442 
1443     case HFINTOSC:
1444         val_osccon |= HFIOFS | HFIOFR;
1445         break;
1446     }
1447 
1448     value.put(val_osccon);
1449     CDprintf(("OSCCON_HS2 osccon 0x%x val_osccon 0x%x\n", value.get(), val_osccon));
1450 }
1451 
1452 
por_wake()1453 void OSCCON_HS2::por_wake()
1454 {
1455     CDprintf(("OSCCON_HS2 config_xosc=%d config_ieso=%d\n", config_xosc, config_ieso));
1456     CDprintf(("OSCCON_HS2 POR  f=%4.1e osccon=0x%x por_value=0x%x\n", cpu_pic->get_frequency(), value.get(), por_value.data));
1457 
1458     if (future_cycle)
1459     {
1460         get_cycles().clear_break(future_cycle);
1461         future_cycle = 0;
1462     }
1463 
1464     // internal RC osc
1465     if (internal_RC())
1466     {
1467         CDprintf(("OSCCON_HS2internal RC clock_state %u osccon %x \n", clock_state, val_osccon));
1468         set_rc_frequency();
1469 
1470         if (future_cycle)
1471         {
1472             get_cycles().clear_break(future_cycle);
1473         }
1474 
1475         future_cycle = get_cycles().get() + irc_por_time();
1476         get_cycles().set_break(future_cycle, this);
1477         return;
1478     }
1479 }
1480 
1481 
put(unsigned int new_value)1482 void WDTCON::put(unsigned int new_value)
1483 {
1484     unsigned int masked_value = new_value & valid_bits;
1485     trace.raw(write_trace.get() | value.get());
1486     value.put(masked_value);
1487 
1488     if (valid_bits > 1)
1489     {
1490         cpu_pic->wdt.set_prescale(masked_value >> 1);
1491     }
1492 
1493     if (cpu_pic->swdten_active())
1494     {
1495         cpu_pic->wdt.swdten((masked_value & SWDTEN) == SWDTEN);
1496     }
1497 }
1498 
1499 
reset(RESET_TYPE)1500 void WDTCON::reset(RESET_TYPE )
1501 {
1502     putRV(por_value);
1503 }
1504 
1505 
1506 //
1507 //--------------------------------------------------
1508 // member functions for the FSR class
1509 //--------------------------------------------------
1510 //
FSR(Processor * pCpu,const char * pName,const char * pDesc)1511 FSR::FSR(Processor *pCpu, const char *pName, const char *pDesc)
1512     : sfr_register(pCpu, pName, pDesc)
1513 {
1514 }
1515 
1516 
put(unsigned int new_value)1517 void  FSR::put(unsigned int new_value)
1518 {
1519     trace.raw(write_trace.get() | value.get());
1520     value.put(new_value);
1521 }
1522 
1523 
put_value(unsigned int new_value)1524 void  FSR::put_value(unsigned int new_value)
1525 {
1526     put(new_value);
1527     update();
1528     cpu_pic->indf->update();
1529 }
1530 
1531 
get()1532 unsigned int FSR::get()
1533 {
1534     trace.raw(read_trace.get() | value.get());
1535     return value.get();
1536 }
1537 
1538 
get_value()1539 unsigned int FSR::get_value()
1540 {
1541     return value.get();
1542 }
1543 
1544 
1545 //
1546 //--------------------------------------------------
1547 // member functions for the FSR_12 class
1548 //--------------------------------------------------
1549 //
FSR_12(Processor * pCpu,const char * pName,unsigned int _rpb,unsigned int _valid_bits)1550 FSR_12::FSR_12(Processor *pCpu, const char *pName, unsigned int _rpb, unsigned int _valid_bits)
1551     : FSR(pCpu, pName, ""),
1552       valid_bits(_valid_bits),
1553       register_page_bits(_rpb)
1554 {
1555 }
1556 
1557 
put(unsigned int new_value)1558 void  FSR_12::put(unsigned int new_value)
1559 {
1560     trace.raw(write_trace.get() | value.get());
1561     value.put(new_value);
1562     /* The 12-bit core selects the register page using the fsr */
1563     cpu_pic->register_bank = &cpu_pic->registers[ value.get() & register_page_bits ];
1564 }
1565 
1566 
put_value(unsigned int new_value)1567 void  FSR_12::put_value(unsigned int new_value)
1568 {
1569     put(new_value);
1570     update();
1571     cpu_pic->indf->update();
1572 }
1573 
1574 
get()1575 unsigned int FSR_12::get()
1576 {
1577     unsigned int v = get_value();
1578     trace.raw(read_trace.get() | value.get());
1579     return v;
1580 }
1581 
1582 
get_value()1583 unsigned int FSR_12::get_value()
1584 {
1585     // adjust for missing bits
1586     return ((value.get() & valid_bits) | (~valid_bits & 0xff));
1587 }
1588 
1589 
1590 //
1591 //--------------------------------------------------
1592 // member functions for the Status_register class
1593 //--------------------------------------------------
1594 //
1595 
1596 //--------------------------------------------------
1597 
Status_register(Processor * pCpu,const char * pName,const char * pDesc)1598 Status_register::Status_register(Processor *pCpu, const char *pName, const char *pDesc)
1599     : sfr_register(pCpu, pName, pDesc)
1600 {
1601     address = 3;
1602     write_mask = 0xff & ~STATUS_TO & ~STATUS_PD;
1603     new_name("status");
1604 }
1605 
1606 
1607 //--------------------------------------------------
reset(RESET_TYPE r)1608 void Status_register::reset(RESET_TYPE r)
1609 {
1610     switch (r)
1611     {
1612     case POR_RESET:
1613         putRV(por_value);
1614         put_TO(1);
1615         put_PD(1);
1616         break;
1617 
1618     case WDT_RESET:
1619         put_TO(0);
1620         break;
1621 
1622     default:
1623         break;
1624     }
1625 }
1626 
1627 
1628 //--------------------------------------------------
1629 // put
1630 
put(unsigned int new_value)1631 void Status_register::put(unsigned int new_value)
1632 {
1633     trace.raw(write_trace.get() | value.get());
1634     value.put((value.get() & ~write_mask) | (new_value & write_mask));
1635 
1636     if (cpu_pic->base_isa() == _14BIT_PROCESSOR_)
1637     {
1638         cpu_pic->register_bank = &cpu_pic->registers[(value.get() & rp_mask) << 2];
1639     }
1640 }
1641 
1642 
1643 //--------------------------------------------------
1644 // get
1645 //unsigned int Status_register::get()
1646 
1647 //--------------------------------------------------
1648 // put_Z
1649 
1650 //void Status_register::put_Z(unsigned int new_z)
1651 
1652 //--------------------------------------------------
1653 // get_Z
1654 //unsigned int Status_register::get_Z()
1655 //--------------------------------------------------
1656 // put_C
1657 
1658 //void Status_register::put_C(unsigned int new_c)
1659 
1660 //--------------------------------------------------
1661 // get_C
1662 //unsigned int Status_register::get_C()
1663 
1664 //--------------------------------------------------
1665 // put_Z_C_DC
1666 
1667 //--------------------------------------------------
1668 // member functions for the INDF class
1669 //--------------------------------------------------
INDF(Processor * pCpu,const char * pName,const char * pDesc)1670 INDF::INDF(Processor *pCpu, const char *pName, const char *pDesc)
1671     : sfr_register(pCpu, pName, pDesc)
1672 {
1673     fsr_mask = 0x7f;           // assume a 14bit core
1674     base_address_mask1 = 0;    //   "          "
1675     base_address_mask2 = 0xff; //   "          "
1676 }
1677 
1678 
initialize()1679 void INDF::initialize()
1680 {
1681     switch (cpu_pic->base_isa())
1682     {
1683     case _12BIT_PROCESSOR_:
1684         fsr_mask = 0x1f;
1685         base_address_mask1 = 0x0;
1686         base_address_mask2 = 0x1f;
1687         break;
1688 
1689     case _14BIT_PROCESSOR_:
1690         fsr_mask = 0x7f;
1691         break;
1692 
1693     case _PIC17_PROCESSOR_:
1694     case _PIC18_PROCESSOR_:
1695         std::cout << "BUG: INDF::" << __FUNCTION__ << ". 16bit core uses a different class for indf.";
1696         break;
1697 
1698     default:
1699         std::cout << " BUG - invalid processor type INDF::initialize\n";
1700     }
1701 }
1702 
1703 
put(unsigned int new_value)1704 void INDF::put(unsigned int new_value)
1705 {
1706     trace.raw(write_trace.get() | value.get());
1707     //trace.register_write(address,value.get());
1708     int reg = (cpu_pic->fsr->get_value() + //cpu_pic->fsr->value +
1709                ((cpu_pic->status->value.get() & base_address_mask1) << 1)) &  base_address_mask2;
1710 
1711     // if the fsr is 0x00 or 0x80, then it points to the indf
1712     if (reg & fsr_mask)
1713     {
1714         cpu_pic->registers[reg]->put(new_value);
1715         //(cpu_pic->fsr->value & base_address_mask2) + ((cpu_pic->status->value & base_address_mask1)<<1)
1716     }
1717 }
1718 
1719 
put_value(unsigned int new_value)1720 void INDF::put_value(unsigned int new_value)
1721 {
1722     // go ahead and use the regular put to write the data.
1723     // note that this is a 'virtual' function. Consequently,
1724     // all objects derived from a file_register should
1725     // automagically be correctly updated (which isn't
1726     // necessarily true if we just write new_value on top
1727     // of the current register value).
1728     put(new_value);
1729     update();
1730     int r = (cpu_pic->fsr->get_value() + //cpu_pic->fsr->value +
1731              (((cpu_pic->status->value.get() & base_address_mask1) << 1)& base_address_mask2));
1732 
1733     if (r & fsr_mask)
1734     {
1735         cpu_pic->registers[r]->update();
1736     }
1737 }
1738 
1739 
get()1740 unsigned int INDF::get()
1741 {
1742     trace.raw(read_trace.get() | value.get());
1743     //trace.register_read(address,value.get());
1744     int reg = (cpu_pic->fsr->get_value() +
1745                ((cpu_pic->status->value.get() & base_address_mask1) << 1)) &  base_address_mask2;
1746 
1747     if (reg & fsr_mask)
1748     {
1749         return (cpu_pic->registers[reg]->get());
1750 
1751     }
1752     else
1753     {
1754         return 0;  // avoid infinite loop if fsr points to the indf
1755     }
1756 }
1757 
1758 
get_value()1759 unsigned int INDF::get_value()
1760 {
1761     int reg = (cpu_pic->fsr->get_value() +
1762                ((cpu_pic->status->value.get() & base_address_mask1) << 1)) &  base_address_mask2;
1763 
1764     if (reg & fsr_mask)
1765     {
1766         return cpu_pic->registers[reg]->get_value();
1767 
1768     }
1769     else
1770     {
1771         return 0;  // avoid infinite loop if fsr points to the indf
1772     }
1773 }
1774 
1775 
1776 //--------------------------------------------------
1777 // member functions for the PCL base class
1778 //--------------------------------------------------
PCL(Processor * pCpu,const char * pName,const char * pDesc)1779 PCL::PCL(Processor *pCpu, const char *pName, const char *pDesc)
1780     : sfr_register(pCpu, pName, pDesc)
1781 {
1782     por_value = RegisterValue(0, 0);
1783 }
1784 
1785 
1786 // %%% FIX ME %%% breaks are different
put(unsigned int new_value)1787 void PCL::put(unsigned int new_value)
1788 {
1789     trace.raw(write_trace.get() | value.get());
1790     cpu_pic->pc->computed_goto(new_value);
1791     //trace.register_write(address,value.get());
1792 }
1793 
1794 
put_value(unsigned int new_value)1795 void PCL::put_value(unsigned int new_value)
1796 {
1797     value.put(new_value & 0xff);
1798     cpu_pic->pc->put_value((cpu_pic->pc->get_value() & 0xffffff00) | value.get());
1799     // The gui (if present) will be updated in the pc->put_value call.
1800 }
1801 
1802 
get()1803 unsigned int PCL::get()
1804 {
1805     return ((value.get() + 1) & 0xff);
1806 }
1807 
1808 
get_value()1809 unsigned int PCL::get_value()
1810 {
1811     value.put(cpu_pic->pc->get_value() & 0xff);
1812     return ((value.get() + 1) & 0xff);
1813 }
1814 
1815 
1816 //------------------------------------------------------------
1817 // PCL reset
1818 //
reset(RESET_TYPE)1819 void PCL::reset(RESET_TYPE )
1820 {
1821     trace.raw(write_trace.get() | value.get());
1822     putRV_notrace(por_value);
1823 }
1824 
1825 
1826 //--------------------------------------------------
1827 // member functions for the PCLATH base class
1828 //--------------------------------------------------
1829 
PCLATH(Processor * pCpu,const char * pName,const char * pDesc)1830 PCLATH::PCLATH(Processor *pCpu, const char *pName, const char *pDesc)
1831     : sfr_register(pCpu, pName, pDesc)
1832 {
1833     mValidBits = PCLATH_MASK;
1834 }
1835 
1836 
put(unsigned int new_value)1837 void PCLATH::put(unsigned int new_value)
1838 {
1839     trace.raw(write_trace.get() | value.get());
1840     //trace.register_write(address,value.get());
1841     value.put(new_value & mValidBits);
1842 }
1843 
1844 
put_value(unsigned int new_value)1845 void PCLATH::put_value(unsigned int new_value)
1846 {
1847     std::cout << "PCLATH::put_value(" << new_value << ")\n";
1848     value.put(new_value & mValidBits);
1849     // RP - I cannot think of a single possible reason I'd want to affect the real PC here!
1850     //  cpu_pic->pc->put_value( (cpu_pic->pc->get_value() & 0xffff00ff) | (value.get()<<8) );
1851     // The gui (if present) will be updated in the pc->put_value call.
1852 }
1853 
1854 
get()1855 unsigned int PCLATH::get()
1856 {
1857     trace.raw(read_trace.get() | value.get());
1858     //trace.register_read(address,value.get());
1859     return (value.get() & mValidBits);
1860 }
1861 
1862 
1863 //--------------------------------------------------
1864 // member functions for the PCON base class
1865 //--------------------------------------------------
1866 //
PCON(Processor * pCpu,const char * pName,const char * pDesc,unsigned int bitMask)1867 PCON::PCON(Processor *pCpu, const char *pName, const char *pDesc,
1868            unsigned int bitMask)
1869     : sfr_register(pCpu, pName, pDesc), valid_bits(bitMask)
1870 {
1871 }
1872 
1873 
put(unsigned int new_value)1874 void PCON::put(unsigned int new_value)
1875 {
1876     Dprintf((" value %x add %x\n", new_value, new_value & valid_bits));
1877     trace.raw(write_trace.get() | value.get());
1878     //trace.register_write(address,value.get());
1879     value.put(new_value & valid_bits);
1880 }
1881 
1882 
1883 //------------------------------------------------
1884 
Indirect_Addressing14(pic_processor * pCpu,const std::string & n)1885 Indirect_Addressing14::Indirect_Addressing14(pic_processor *pCpu, const std::string &n)
1886     : cpu(pCpu),
1887       fsrl(pCpu, (std::string("fsrl") + n).c_str(), "FSR Low", this),
1888       fsrh(pCpu, (std::string("fsrh") + n).c_str(), "FSR High", this),
1889       indf(pCpu, (std::string("indf") + n).c_str(), "Indirect Register", this)
1890 {
1891     current_cycle = (guint64)(-1);   // Not zero! See bug #3311944
1892 }
1893 
1894 
1895 /*
1896  * put - Each of the indirect registers associated with this
1897  * indirect addressing class will call this routine to indirectly
1898  * write data.
1899  */
put(unsigned int new_value)1900 void Indirect_Addressing14::put(unsigned int new_value)
1901 {
1902     unsigned int fsr_adj = fsr_value + fsr_delta;
1903 
1904     if (fsr_adj < 0x1000)  	// Traditional Data Memory
1905     {
1906         if (is_indirect_register(fsr_adj))
1907         {
1908             return;
1909         }
1910 
1911         cpu_pic->registers[fsr_adj]->put(new_value);
1912 
1913     }
1914     else if (fsr_adj >= 0x2000 && fsr_adj < 0x29b0)     // Linear GPR region
1915     {
1916         unsigned int bank = (fsr_adj & 0xfff) / 0x50;
1917         unsigned int low_bits = ((fsr_adj & 0xfff) % 0x50) + 0x20;
1918         Dprintf(("fsr_adj %x bank %x low_bits %x add %x\n", fsr_adj, bank, low_bits, (bank * 0x80 + low_bits)));
1919         cpu_pic->registers[bank * 0x80 + low_bits]->put(new_value);
1920 
1921     }
1922     else if (fsr_adj >= 0x8000 && fsr_adj <= 0xffff)     // program memory
1923     {
1924         std::cout << "WARNING cannot write via FSR/INDF to program memory address 0x"
1925                   << std::hex << fsr_adj << '\n';
1926         return;	// Not writable
1927     }
1928 }
1929 
1930 
1931 /*
1932  * get - Each of the indirect registers associated with this
1933  * indirect addressing class will call this routine to indirectly
1934  * retrieve data.
1935  */
get()1936 unsigned int Indirect_Addressing14::get()
1937 {
1938     unsigned int fsr_adj = fsr_value + fsr_delta;
1939 
1940     if (fsr_adj < 0x1000)   // Traditional Data Memory
1941     {
1942         if (is_indirect_register(fsr_adj))
1943         {
1944             return 0;
1945         }
1946 
1947         return cpu_pic->registers[fsr_adj]->get();
1948 
1949     }
1950     else if (fsr_adj >= 0x2000 && fsr_adj < 0x29b0)     // Linear GPR region
1951     {
1952         unsigned int bank = (fsr_adj & 0xfff) / 0x50;
1953         unsigned int low_bits = ((fsr_adj & 0xfff) % 0x50) + 0x20;
1954         return (cpu_pic->registers[bank * 0x80 + low_bits]->get());
1955 
1956     }
1957     else if (fsr_adj >= 0x8000 && fsr_adj <= 0xffff)     // program memory
1958     {
1959         unsigned address = fsr_adj - 0x8000;
1960 
1961         if (address <= cpu_pic->program_memory_size())
1962         {
1963             unsigned int pm = cpu_pic->get_program_memory_at_address(address);
1964             Dprintf((" address %x max %x value %x\n", address, cpu_pic->program_memory_size(), pm));
1965             return pm & 0xff;
1966         }
1967     }
1968 
1969     return 0;
1970 }
1971 
1972 
1973 /*
1974  * get - Each of the indirect registers associated with this
1975  * indirect addressing class will call this routine to indirectly
1976  * retrieve data.
1977  */
get_value()1978 unsigned int Indirect_Addressing14::get_value()
1979 {
1980     unsigned int fsr_adj = fsr_value + fsr_delta;
1981 
1982     if (fsr_adj < 0x1000)  	// Traditional Data Memory
1983     {
1984         if (is_indirect_register(fsr_adj))
1985         {
1986             return 0;
1987         }
1988 
1989         return cpu_pic->registers[fsr_adj]->get_value();
1990 
1991     }
1992     else if (fsr_adj >= 0x2000 && fsr_adj < 0x29b0)     // Linear GPR region
1993     {
1994         unsigned int bank = (fsr_adj & 0xfff) / 0x50;
1995         unsigned int low_bits = ((fsr_adj & 0xfff) % 0x50) + 0x20;
1996         return (cpu_pic->registers[bank * 0x80 + low_bits]->get_value());
1997 
1998     }
1999     else if (fsr_adj >= 0x8000 && fsr_adj <= 0xffff)     // program memory
2000     {
2001         unsigned address = fsr_adj - 0x8000;
2002 
2003         if (address <= cpu_pic->program_memory_size())
2004         {
2005             unsigned int pm = cpu_pic->get_program_memory_at_address(address);
2006             return pm & 0xff;
2007         }
2008     }
2009 
2010     return 0;
2011 }
2012 
2013 
put_fsr(unsigned int new_fsr)2014 void Indirect_Addressing14::put_fsr(unsigned int new_fsr)
2015 {
2016     fsrl.put(new_fsr & 0xff);
2017     fsrh.put((new_fsr >> 8) & 0xff);
2018 }
2019 
2020 
2021 /*
2022  * update_fsr_value - This routine is called by the FSRL and FSRH
2023  * classes. It's purpose is to update the 16-bit
2024  * address formed by the concatenation of FSRL and FSRH.
2025  *
2026  */
2027 
update_fsr_value()2028 void Indirect_Addressing14::update_fsr_value()
2029 {
2030     if (current_cycle != get_cycles().get())
2031     {
2032         fsr_value = (fsrh.value.get() << 8) |  fsrl.value.get();
2033         fsr_delta = 0;
2034     }
2035 }
2036 
2037 
2038 //--------------------------------------------------
2039 // member functions for the FSR class
2040 //--------------------------------------------------
2041 //
FSRL14(Processor * pCpu,const char * pName,const char * pDesc,Indirect_Addressing14 * pIAM)2042 FSRL14::FSRL14(Processor *pCpu, const char *pName, const char *pDesc, Indirect_Addressing14 *pIAM)
2043     : sfr_register(pCpu, pName, pDesc),
2044       iam(pIAM)
2045 {
2046 }
2047 
2048 
put(unsigned int new_value)2049 void  FSRL14::put(unsigned int new_value)
2050 {
2051     trace.raw(write_trace.get() | value.get());
2052     value.put(new_value & 0xff);
2053     iam->fsr_delta = 0;
2054     iam->update_fsr_value();
2055 }
2056 
2057 
put_value(unsigned int new_value)2058 void  FSRL14::put_value(unsigned int new_value)
2059 {
2060     value.put(new_value & 0xff);
2061     iam->fsr_delta = 0;
2062     iam->update_fsr_value();
2063     update();
2064     cpu14->indf->update();
2065 }
2066 
2067 
FSRH14(Processor * pCpu,const char * pName,const char * pDesc,Indirect_Addressing14 * pIAM)2068 FSRH14::FSRH14(Processor *pCpu, const char *pName, const char *pDesc, Indirect_Addressing14 *pIAM)
2069     : sfr_register(pCpu, pName, pDesc),
2070       iam(pIAM)
2071 {
2072 }
2073 
2074 
put(unsigned int new_value)2075 void  FSRH14::put(unsigned int new_value)
2076 {
2077     trace.raw(write_trace.get() | value.get());
2078     value.put(new_value & 0xff);
2079     iam->update_fsr_value();
2080 }
2081 
2082 
put_value(unsigned int new_value)2083 void  FSRH14::put_value(unsigned int new_value)
2084 {
2085     value.put(new_value & 0xff);
2086     iam->update_fsr_value();
2087     update();
2088     cpu14->indf->update();
2089 }
2090 
2091 
2092 // INDF14 used by 14bit enhanced indirect addressing
INDF14(Processor * pCpu,const char * pName,const char * pDesc,Indirect_Addressing14 * pIAM)2093 INDF14::INDF14(Processor *pCpu, const char *pName, const char *pDesc, Indirect_Addressing14 *pIAM)
2094     : sfr_register(pCpu, pName, pDesc),
2095       iam(pIAM)
2096 {
2097 }
2098 
2099 
put(unsigned int new_value)2100 void INDF14::put(unsigned int new_value)
2101 {
2102     trace.raw(write_trace.get() | value.get());
2103 
2104     if (iam->fsr_value & 0x8000)   // extra cycle for program memory access
2105     {
2106         get_cycles().increment();
2107     }
2108 
2109     iam->put(new_value);
2110     iam->fsr_delta = 0;
2111 }
2112 
2113 
put_value(unsigned int new_value)2114 void INDF14::put_value(unsigned int new_value)
2115 {
2116     iam->put(new_value);
2117     iam->fsr_delta = 0;
2118     update();
2119 }
2120 
2121 
get()2122 unsigned int INDF14::get()
2123 {
2124     unsigned int ret;
2125     Dprintf((" get val %x delta %x \n", iam->fsr_value, iam->fsr_delta));
2126     trace.raw(read_trace.get() | value.get());
2127 
2128     if (iam->fsr_value & 0x8000)
2129     {
2130         get_cycles().increment();
2131     }
2132 
2133     ret = iam->get();
2134     iam->fsr_delta = 0;
2135     return ret;
2136 }
2137 
2138 
get_value()2139 unsigned int INDF14::get_value()
2140 {
2141     return iam->get_value();
2142 }
2143 
2144 
2145 //--------------------------------------------------
Stack(Processor * pCpu)2146 Stack::Stack(Processor *pCpu) : cpu(pCpu)
2147 {
2148     std::fill_n(contents, 32, 0);
2149 }
2150 
2151 
2152 //
2153 // Stack::push
2154 //
2155 // push the passed address onto the stack by storing it at the current
2156 //
2157 
push(unsigned int address)2158 bool Stack::push(unsigned int address)
2159 {
2160     Dprintf(("pointer=%d address 0x%x\n", pointer, address));
2161     // Write the address at the current point location. Note that the '& stack_mask'
2162     // implicitly handles the stack wrap around.
2163 
2164     // If the stack pointer is too big, then the stack has definitely over flowed.
2165     // However, some pic programs take advantage of this 'feature', so provide a means
2166     // for them to ignore the warnings.
2167 
2168     if (pointer > (int)stack_mask)
2169     {
2170         stack_overflow();
2171         return false;
2172     }
2173 
2174     contents[pointer++ & stack_mask] = address;
2175     return true;
2176 }
2177 
2178 
stack_overflow()2179 bool Stack::stack_overflow()
2180 {
2181     Dprintf(("stack_warnings_flag=%d break_on_overflow=%d\n", stack_warnings_flag, break_on_overflow));
2182 
2183     if (stack_warnings_flag || break_on_overflow)
2184     {
2185         std::cout << "stack overflow \n";
2186     }
2187 
2188     if (break_on_overflow)
2189     {
2190         bp.halt();
2191     }
2192 
2193     return true;
2194 }
2195 
2196 
2197 //
2198 // Stack::pop
2199 //
2200 
pop()2201 unsigned int Stack::pop()
2202 {
2203     // First decrement the stack pointer.
2204     if (--pointer < 0)
2205     {
2206         stack_underflow();
2207         return 0;
2208     }
2209 
2210     Dprintf(("pointer=%d address 0x%x\n", pointer, contents[pointer & stack_mask]));
2211     return (contents[pointer & stack_mask]);
2212 }
2213 
2214 
stack_underflow()2215 bool Stack::stack_underflow()
2216 {
2217     pointer = 0;
2218 
2219     if (stack_warnings_flag || break_on_underflow)
2220     {
2221         std::cout << "stack underflow ";
2222     }
2223 
2224     if (break_on_underflow)
2225     {
2226         bp.halt();
2227     }
2228 
2229     return true;
2230 }
2231 
2232 
2233 //
2234 //  bool Stack::set_break_on_overflow(bool clear_or_set)
2235 //
2236 //  Set or clear the break on overflow flag
2237 
2238 
set_break_on_overflow(bool clear_or_set)2239 bool Stack::set_break_on_overflow(bool clear_or_set)
2240 {
2241     if (break_on_overflow == clear_or_set)
2242     {
2243         return false;
2244     }
2245 
2246     break_on_overflow = clear_or_set;
2247     return true;
2248 }
2249 
2250 //
2251 //  bool Stack::set_break_on_underflow(bool clear_or_set)
2252 //
2253 //  Set or clear the break on underflow flag
2254 
2255 
set_break_on_underflow(bool clear_or_set)2256 bool Stack::set_break_on_underflow(bool clear_or_set)
2257 {
2258     if (break_on_underflow == clear_or_set)
2259     {
2260         return false;
2261     }
2262 
2263     break_on_underflow = clear_or_set;
2264     return true;
2265 }
2266 
2267 
2268 // Read value at top of stack
2269 //
get_tos()2270 unsigned int Stack::get_tos()
2271 {
2272     if (pointer > 0)
2273     {
2274         return contents[pointer - 1];
2275 
2276     }
2277     else
2278     {
2279         return 0;
2280     }
2281 }
2282 
2283 
2284 // Modify value at top of stack;
2285 //
put_tos(unsigned int new_tos)2286 void Stack::put_tos(unsigned int new_tos)
2287 {
2288     if (pointer > 0)
2289     {
2290         contents[pointer - 1] = new_tos;
2291     }
2292 }
2293 
2294 
2295 // Stack14E for extended 14bit processors
2296 // This stack implementation differs from both the other 14bit
2297 // and 16bit stacks as a dummy empty location is used so a
2298 // stack with 16 slots can hold 16 values. The other implementaion
2299 // of the stack hold n-1 values for an n slot stack.
2300 // This stack also supports stkptr, tosl, and tosh like the 16bit
2301 // (p18) processors
Stack14E(Processor * pCpu)2302 Stack14E::Stack14E(Processor *pCpu) : Stack(pCpu),
2303     stkptr(pCpu, "stkptr", "Stack pointer"),
2304     tosl(pCpu, "tosl", "Top of Stack low byte"),
2305     tosh(pCpu, "tosh", "Top of Stack high byte")
2306 {
2307     stkptr.stack = this;
2308     tosl.stack = this;
2309     tosh.stack = this;
2310     STVREN = true;
2311 }
2312 
2313 
~Stack14E()2314 Stack14E::~Stack14E()
2315 {
2316     pic_processor *pCpu = dynamic_cast<pic_processor *>(cpu);
2317 
2318     if (pCpu)
2319     {
2320         pCpu->remove_sfr_register(&stkptr);
2321         pCpu->remove_sfr_register(&tosl);
2322         pCpu->remove_sfr_register(&tosh);
2323     }
2324 }
2325 
2326 
reset(RESET_TYPE)2327 void Stack14E::reset(RESET_TYPE )
2328 {
2329     pointer = NO_ENTRY;
2330 
2331     if (STVREN)
2332     {
2333         contents[stack_mask] = 0;
2334 
2335     }
2336     else
2337     {
2338         contents[pointer - 1] = contents[stack_mask];
2339     }
2340 
2341     Dprintf((" pointer 0x%x\n", pointer));
2342     stkptr.put(pointer - 1);
2343 }
2344 
2345 
push(unsigned int address)2346 bool Stack14E::push(unsigned int address)
2347 {
2348     Dprintf(("pointer=%d address 0x%x\n", pointer, address));
2349     // Write the address at the current point location. Note that the '& stack_mask'
2350     // implicitly handles the stack wrap around.
2351 
2352     if (pointer == NO_ENTRY)
2353     {
2354         pointer = 0;
2355     }
2356 
2357     contents[pointer & stack_mask] = address;
2358 
2359     // If the stack pointer is too big, then the stack has definitely over flowed.
2360     // However, some pic programs take advantage of this 'feature', so provide a means
2361     // for them to ignore the warnings.
2362 
2363     if (pointer++ > (int)stack_mask)
2364     {
2365         return stack_overflow();
2366     }
2367 
2368     stkptr.put(pointer - 1);
2369     return true;
2370 }
2371 
2372 
pop()2373 unsigned int  Stack14E::pop()
2374 {
2375     unsigned int ret = 0;
2376 
2377     if (pointer == NO_ENTRY)
2378     {
2379         return stack_underflow();
2380     }
2381 
2382     pointer--;
2383     ret = contents[pointer];
2384 
2385     if (pointer <= 0)
2386     {
2387         pointer = NO_ENTRY;
2388     }
2389 
2390     stkptr.put(pointer - 1);
2391     return ret;
2392 }
2393 
2394 
stack_overflow()2395 bool Stack14E::stack_overflow()
2396 {
2397     cpu14e->pcon.put(cpu14e->pcon.get() | PCON::STKOVF);
2398 
2399     if (STVREN)
2400     {
2401         cpu->reset(STKOVF_RESET);
2402         return false;
2403 
2404     }
2405     else
2406     {
2407         std::cout << "Stack overflow\n";
2408     }
2409 
2410     return true;
2411 }
2412 
2413 
stack_underflow()2414 bool Stack14E::stack_underflow()
2415 {
2416     Dprintf((" cpu %p STVREN %d\n", cpu, STVREN));
2417     cpu14e->pcon.put(cpu14e->pcon.get() | PCON::STKUNF);
2418 
2419     if (STVREN)
2420     {
2421         cpu->reset(STKUNF_RESET);
2422         return false;
2423 
2424     }
2425     else
2426     {
2427         std::cout << "Stack underflow\n";
2428     }
2429 
2430     return true;
2431 }
2432 
2433 
2434 //------------------------------------------------
2435 // TOSL
TOSL(Processor * pCpu,const char * pName,const char * pDesc)2436 TOSL::TOSL(Processor *pCpu, const char *pName, const char *pDesc)
2437     : sfr_register(pCpu, pName, pDesc)
2438 {
2439 }
2440 
2441 
get()2442 unsigned int TOSL::get()
2443 {
2444     value.put(stack->get_tos() & 0xff);
2445     trace.raw(read_trace.get() | value.get());
2446     return value.get();
2447 }
2448 
2449 
get_value()2450 unsigned int TOSL::get_value()
2451 {
2452     value.put(stack->get_tos() & 0xff);
2453     return value.get();
2454 }
2455 
2456 
put(unsigned int new_value)2457 void TOSL::put(unsigned int new_value)
2458 {
2459     trace.raw(write_trace.get() | value.get());
2460     stack->put_tos((stack->get_tos() & 0xffffff00) | (new_value & 0xff));
2461     value.put(new_value & 0xff);
2462 }
2463 
2464 
put_value(unsigned int new_value)2465 void TOSL::put_value(unsigned int new_value)
2466 {
2467     stack->put_tos((stack->get_tos() & 0xffffff00) | (new_value & 0xff));
2468     value.put(new_value & 0xff);
2469     update();
2470 }
2471 
2472 
2473 //------------------------------------------------
2474 // TOSH
TOSH(Processor * pCpu,const char * pName,const char * pDesc)2475 TOSH::TOSH(Processor *pCpu, const char *pName, const char *pDesc)
2476     : sfr_register(pCpu, pName, pDesc)
2477 {
2478 }
2479 
2480 
get()2481 unsigned int TOSH::get()
2482 {
2483     value.put((stack->get_tos() >> 8) & 0xff);
2484     trace.raw(read_trace.get() | value.get());
2485     return value.get();
2486 }
2487 
2488 
get_value()2489 unsigned int TOSH::get_value()
2490 {
2491     value.put((stack->get_tos() >> 8) & 0xff);
2492     return value.get();
2493 }
2494 
2495 
put(unsigned int new_value)2496 void TOSH::put(unsigned int new_value)
2497 {
2498     trace.raw(write_trace.get() | value.get());
2499     stack->put_tos((stack->get_tos() & 0xffff00ff) | ((new_value & 0xff) << 8));
2500     value.put(new_value & 0xff);
2501 }
2502 
2503 
put_value(unsigned int new_value)2504 void TOSH::put_value(unsigned int new_value)
2505 {
2506     stack->put_tos((stack->get_tos() & 0xffff00ff) | ((new_value & 0xff) << 8));
2507     value.put(new_value & 0xff);
2508     update();
2509 }
2510 
2511 
STKPTR(Processor * pCpu,const char * pName,const char * pDesc)2512 STKPTR::STKPTR(Processor *pCpu, const char *pName, const char *pDesc)
2513     : sfr_register(pCpu, pName, pDesc)
2514 {
2515 }
2516 
2517 
put_value(unsigned int new_value)2518 void STKPTR::put_value(unsigned int new_value)
2519 {
2520     stack->pointer = (new_value & 0x1f) + 1;
2521     value.put(new_value);
2522     update();
2523 }
2524 
2525 
put(unsigned int new_value)2526 void STKPTR::put(unsigned int new_value)
2527 {
2528     trace.raw(write_trace.get() | value.get());
2529     put_value(new_value);
2530 }
2531 
2532 
2533 //========================================================================
2534 class WReadTraceObject : public RegisterReadTraceObject
2535 {
2536 public:
2537     WReadTraceObject(Processor *_cpu, RegisterValue trv);
2538     virtual void print(FILE *fp) override;
2539 };
2540 
2541 
2542 class WWriteTraceObject : public RegisterWriteTraceObject
2543 {
2544 public:
2545     WWriteTraceObject(Processor *_cpu, RegisterValue trv);
2546     virtual void print(FILE *fp) override;
2547 };
2548 
2549 
2550 class WTraceType : public ProcessorTraceType
2551 {
2552 public:
WTraceType(Processor * _cpu,unsigned int s)2553     WTraceType(Processor *_cpu, unsigned int s)
2554         : ProcessorTraceType(_cpu, s, "W reg")
2555     {}
2556 
2557     TraceObject *decode(unsigned int tbi) override;
2558 };
2559 
2560 
2561 //========================================================================
WWriteTraceObject(Processor * _cpu,RegisterValue trv)2562 WWriteTraceObject::WWriteTraceObject(Processor *_cpu, RegisterValue trv)
2563     : RegisterWriteTraceObject(_cpu, 0, trv)
2564 {
2565     pic_processor *pcpu = dynamic_cast<pic_processor *>(cpu);
2566 
2567     if (pcpu)
2568     {
2569         to = cpu_pic->Wreg->trace_state;
2570         cpu_pic->Wreg->trace_state = from;
2571     }
2572 }
2573 
2574 
print(FILE * fp)2575 void WWriteTraceObject::print(FILE *fp)
2576 {
2577     char sFrom[16];
2578     char sTo[16];
2579     fprintf(fp, "  Wrote: 0x%s to W was 0x%s\n",
2580             to.toString(sTo, sizeof(sTo)),
2581             from.toString(sFrom, sizeof(sFrom)));
2582 }
2583 
2584 
2585 //========================================================================
WReadTraceObject(Processor * _cpu,RegisterValue trv)2586 WReadTraceObject::WReadTraceObject(Processor *_cpu, RegisterValue trv)
2587     : RegisterReadTraceObject(_cpu, 0, trv)
2588 {
2589     pic_processor *pcpu = dynamic_cast<pic_processor *>(cpu);
2590 
2591     if (pcpu)
2592     {
2593         to = cpu_pic->Wreg->trace_state;
2594         cpu_pic->Wreg->trace_state = from;
2595     }
2596 }
2597 
2598 
print(FILE * fp)2599 void WReadTraceObject::print(FILE *fp)
2600 {
2601     char sFrom[16];
2602     fprintf(fp, "  Read: 0x%s from W\n",
2603             from.toString(sFrom, sizeof(sFrom)));
2604 }
2605 
2606 
2607 //========================================================================
decode(unsigned int tbi)2608 TraceObject * WTraceType::decode(unsigned int tbi)
2609 {
2610     unsigned int tv = trace.get(tbi);
2611     RegisterValue rv = RegisterValue(tv & 0xff, 0);
2612     TraceObject *wto;
2613 
2614     if (tv & (1 << 22))
2615     {
2616         wto = new WReadTraceObject(cpu, rv);
2617 
2618     }
2619     else
2620     {
2621         wto = new WWriteTraceObject(cpu, rv);
2622     }
2623 
2624     return wto;
2625 }
2626 
2627 
WREG(Processor * pCpu,const char * pName,const char * pDesc)2628 WREG::WREG(Processor *pCpu, const char *pName, const char *pDesc)
2629     : sfr_register(pCpu, pName, pDesc)
2630 {
2631     if (cpu)
2632     {
2633         unsigned int trace_command = trace.allocateTraceType(m_tt = new WTraceType(get_cpu(), 1));
2634         RegisterValue rv(trace_command + (0 << 22), trace_command + (2 << 22));
2635         set_write_trace(rv);
2636         rv = RegisterValue(trace_command + (1 << 22), trace_command + (3 << 22));
2637         set_read_trace(rv);
2638     }
2639 }
2640 
2641 
~WREG()2642 WREG::~WREG()
2643 {
2644     delete m_tt;
2645 }
2646 
2647 
put(unsigned int new_value)2648 void WPU::put(unsigned int new_value)
2649 {
2650     unsigned int masked_value = new_value & mValidBits;
2651     int i;
2652     trace.raw(write_trace.get() | value.get());
2653     value.put(masked_value);
2654 
2655     for (i = 0; i < 8; i++)
2656     {
2657         if ((1 << i) & mValidBits)
2658         {
2659             (&(*wpu_gpio)[i])->getPin().update_pullup((((1 << i) & masked_value) && wpu_pu) ? '1' : '0', true);
2660         }
2661     }
2662 }
2663 
2664 
2665 /*
2666  * enable/disable all WPU  pullups
2667  */
set_wpu_pu(bool pullup_enable)2668 void WPU::set_wpu_pu(bool pullup_enable)
2669 {
2670     if (pullup_enable != wpu_pu)
2671     {
2672         wpu_pu = pullup_enable;
2673         put(value.get());	// change pull-ups based on value of WPU and gpio_pu
2674     }
2675 }
2676 
2677 // Open Drain Control
put(unsigned int new_value)2678 void ODCON::put(unsigned int new_value)
2679 {
2680     unsigned int masked_value = new_value & mValidBits;
2681     int i;
2682     trace.raw(write_trace.get() | value.get());
2683     value.put(masked_value);
2684 
2685     for (i = 0; i < 8; i++)
2686     {
2687         if ((1 << i) & mValidBits)
2688         {
2689             (&(*gpio)[i])->getPin().open_drain(((1 << i) & masked_value));
2690         }
2691     }
2692 }
2693 
2694 // input threashold Control
put(unsigned int new_value)2695 void INLVL::put(unsigned int new_value)
2696 {
2697     unsigned int masked_value = new_value & mValidBits;
2698     double vdd = ((Processor *)cpu)->get_Vdd();
2699     int i;
2700     trace.raw(write_trace.get() | value.get());
2701     value.put(masked_value);
2702     for (i = 0; i < 8; i++)
2703     {
2704         if ((1 << i) & mValidBits)
2705         {
2706             (&(*gpio)[i])->getPin().set_schmitt_level(((1 << i) & masked_value), vdd);
2707         }
2708     }
2709 }
2710 
CPSCON0(Processor * pCpu,const char * pName,const char * pDesc)2711 CPSCON0::CPSCON0(Processor *pCpu, const char *pName, const char *pDesc)
2712     : sfr_register(pCpu, pName, pDesc)
2713 {
2714     mValidBits = 0xcf;
2715 
2716     for (int i = 0; i < 16; i++)
2717     {
2718         pin[i] = nullptr;
2719     }
2720 }
2721 
2722 
~CPSCON0()2723 CPSCON0::~CPSCON0()
2724 {
2725     delete cps_stimulus;
2726 }
2727 
2728 
put(unsigned int new_value)2729 void CPSCON0::put(unsigned int new_value)
2730 {
2731     unsigned int masked_value = (new_value & mValidBits) & ~CPSOUT;
2732     unsigned int diff = masked_value ^ value.get();
2733     trace.raw(write_trace.get() | value.get());
2734     value.put(masked_value);
2735 
2736     if (diff & T0XCS)
2737     {
2738         m_tmr0->set_t0xcs(masked_value & T0XCS);
2739     }
2740 
2741     calculate_freq();
2742 }
2743 
2744 
2745 #define p_cpu ((Processor *)cpu)
2746 
calculate_freq()2747 void CPSCON0::calculate_freq()
2748 {
2749     if (!(value.get() & CPSON))   // not active, return
2750     {
2751         return;
2752     }
2753 
2754     if (!pin[chan] || !pin[chan]->getPin().snode)
2755     {
2756         return;
2757     }
2758 
2759     double cap = pin[chan]->getPin().snode->Cth;
2760     double current = 0;
2761     double deltat;
2762 
2763     switch ((value.get() & (CPSRNG0 | CPSRNG1)) >> 2)
2764     {
2765     case 1:
2766         current = (value.get() & CPSRM) ? 9e-6 : 0.1e-6;
2767         break;
2768 
2769     case 2:
2770         current = (value.get() & CPSRM) ? 30e-6 : 1.2e-6;
2771         break;
2772 
2773     case 3:
2774         current = (value.get() & CPSRM) ? 100e-6 : 18e-6;
2775         break;
2776     };
2777 
2778     if (current < 1e-12)
2779     {
2780         return;
2781     }
2782 
2783     // deltat is the time required to charge the capacitance on the pin
2784     // from a constant current source for the specified voltage swing.
2785     // The voltage swing for the internal reference is not specified
2786     // and it is just a guess that it is Vdd - 2 diode drops.
2787     //
2788     // This implimentation does not work if capacitor oscillator
2789     // runs faster than Fosc/4
2790     //
2791     if (value.get() & CPSRM)
2792     {
2793         deltat = (FVR_voltage - DAC_voltage) * cap / current;
2794 
2795         if (deltat <= 0.)
2796         {
2797             std::cout << "CPSCON FVR must be greater than DAC for high range to work\n";
2798             return;
2799         }
2800 
2801     }
2802     else
2803     {
2804         deltat = (p_cpu->get_Vdd() - 1.2) * cap / current;
2805     }
2806 
2807     period = (p_cpu->get_frequency() * deltat + 2) / 4;
2808 
2809     if (period <= 0)
2810     {
2811         std::cout << "CPSCON Oscillator > Fosc/4, setting to Fosc/4\n";
2812         period = 1;
2813     }
2814 
2815     guint64 fc = get_cycles().get() + period;
2816 
2817     if (future_cycle > get_cycles().get())
2818     {
2819         get_cycles().reassign_break(future_cycle, fc, this);
2820 
2821     }
2822     else
2823     {
2824         get_cycles().set_break(fc, this);
2825     }
2826 
2827     future_cycle = fc;
2828 }
2829 
2830 
callback_print()2831 void CPSCON0::callback_print()
2832 {
2833     std::cout <<  name() << " has callback, ID = " << CallBackID << '\n';
2834 }
2835 
2836 
callback()2837 void CPSCON0::callback()
2838 {
2839     Dprintf(("now=0x%" PRINTF_GINT64_MODIFIER "x\n", get_cycles().get()));
2840 
2841     if (!(value.get() & CPSON))
2842     {
2843         return;
2844     }
2845 
2846     if (value.get() & CPSOUT)   // High to low transition
2847     {
2848         value.put(value.get() & ~CPSOUT);
2849 
2850         if (m_tmr0 && (value.get() & T0XCS) &&
2851                 m_tmr0->get_t0se() && m_tmr0->get_t0cs())
2852         {
2853             m_tmr0->increment();
2854         }
2855 
2856     }
2857     else  		// Low to high transition
2858     {
2859         value.put(value.get() | CPSOUT);
2860 
2861         if (m_tmr0 && (value.get() & T0XCS) &&
2862                 !m_tmr0->get_t0se() && m_tmr0->get_t0cs())
2863         {
2864             m_tmr0->increment();
2865         }
2866 
2867         if (m_t1con_g)
2868         {
2869             m_t1con_g->t1_cap_increment();
2870         }
2871     }
2872 
2873     calculate_freq();
2874 }
2875 
2876 
set_chan(unsigned int _chan)2877 void CPSCON0::set_chan(unsigned int _chan)
2878 {
2879     if (_chan == chan)
2880     {
2881         return;
2882     }
2883 
2884     if (!pin[_chan])
2885     {
2886         std::cout << "CPSCON Channel " << _chan << " reserved\n";
2887         return;
2888     }
2889 
2890     if (!pin[_chan]->getPin().snode)
2891     {
2892         std::cout << "CPSCON Channel " << pin[_chan]->getPin().name() << " requires a node attached\n";
2893         chan = _chan;
2894         return;
2895     }
2896 
2897     if (!cps_stimulus)
2898     {
2899         cps_stimulus = new CPS_stimulus(this, "cps_stimulus");
2900 
2901     }
2902     else if (pin[_chan]->getPin().snode)
2903     {
2904         (pin[_chan]->getPin().snode)->detach_stimulus(cps_stimulus);
2905     }
2906 
2907     chan = _chan;
2908     (pin[_chan]->getPin().snode)->attach_stimulus(cps_stimulus);
2909     calculate_freq();
2910 }
2911 
2912 
set_DAC_volt(double volt)2913 void CPSCON0::set_DAC_volt(double volt)
2914 {
2915     DAC_voltage = volt;
2916 
2917     if ((value.get() & (CPSON | CPSRM)) == (CPSON | CPSRM))
2918     {
2919         calculate_freq();
2920     }
2921 }
2922 
2923 
set_FVR_volt(double volt)2924 void CPSCON0::set_FVR_volt(double volt)
2925 {
2926     FVR_voltage = volt;
2927 
2928     if ((value.get() & (CPSON | CPSRM)) == (CPSON | CPSRM))
2929     {
2930         calculate_freq();
2931     }
2932 }
2933 
2934 
CPS_stimulus(CPSCON0 * arg,const char * cPname,double _Vth,double _Zth)2935 CPS_stimulus::CPS_stimulus(CPSCON0 * arg, const char *cPname, double _Vth, double _Zth)
2936     : stimulus(cPname, _Vth, _Zth), m_cpscon0(arg)
2937 {
2938 }
2939 
2940 
2941 // Thisvis also called when the capacitance chages,
2942 // not just when the voltage changes
set_nodeVoltage(double v)2943 void CPS_stimulus::set_nodeVoltage(double v)
2944 {
2945     Dprintf(("set_nodeVoltage =%.1f\n", v));
2946     nodeVoltage = v;
2947     m_cpscon0->calculate_freq();
2948 }
2949 
2950 
put(unsigned int new_value)2951 void CPSCON1::put(unsigned int new_value)
2952 {
2953     unsigned int masked_value = new_value & mValidBits;
2954     trace.raw(write_trace.get() | value.get());
2955     value.put(masked_value);
2956     assert(m_cpscon0);
2957     m_cpscon0->set_chan(masked_value);
2958 }
2959 
2960 
SRCON0(Processor * pCpu,const char * pName,const char * pDesc,SR_MODULE * _sr_module)2961 SRCON0::SRCON0(Processor *pCpu, const char *pName, const char *pDesc, SR_MODULE *_sr_module)
2962     : sfr_register(pCpu, pName, pDesc),
2963       m_sr_module(_sr_module)
2964 {
2965 }
2966 
2967 
put(unsigned int new_value)2968 void SRCON0::put(unsigned int new_value)
2969 {
2970     unsigned int diff = new_value ^ value.get();
2971 
2972     if (!diff)
2973     {
2974         return;
2975     }
2976 
2977     trace.raw(write_trace.get() | value.get());
2978     value.put(new_value  & ~(SRPR | SRPS)); // SRPR AND SRPS not saved
2979 
2980     if ((diff & SRPS) && (new_value & SRPS))
2981     {
2982         m_sr_module->pulse_set();
2983     }
2984 
2985     if ((diff & SRPR) && (new_value & SRPR))
2986     {
2987         m_sr_module->pulse_reset();
2988     }
2989 
2990     if (diff & CLKMASK)
2991     {
2992         m_sr_module->clock_diff((new_value & CLKMASK) >> CLKSHIFT);
2993     }
2994 
2995     if (diff & (SRQEN | SRLEN))
2996     {
2997         m_sr_module->Qoutput();
2998     }
2999 
3000     if (diff & (SRNQEN | SRLEN))
3001     {
3002         m_sr_module->NQoutput();
3003     }
3004 
3005     m_sr_module->update();
3006 }
3007 
3008 
SRCON1(Processor * pCpu,const char * pName,const char * pDesc,SR_MODULE * _sr_module)3009 SRCON1::SRCON1(Processor *pCpu, const char *pName, const char *pDesc, SR_MODULE *_sr_module)
3010     : sfr_register(pCpu, pName, pDesc), m_sr_module(_sr_module)
3011 {
3012 }
3013 
3014 
put(unsigned int new_value)3015 void SRCON1::put(unsigned int new_value)
3016 {
3017     unsigned int masked_value = new_value & mValidBits;
3018     unsigned int diff = masked_value ^ value.get();
3019     trace.raw(write_trace.get() | value.get());
3020     value.put(masked_value);
3021 
3022     if (!diff)
3023     {
3024         return;
3025     }
3026 
3027     if (diff & (SRRCKE | SRSCKE))
3028     {
3029         if (!(new_value & (SRRCKE | SRSCKE)))  	// all clocks off
3030         {
3031             m_sr_module->clock_disable();  // turn off clock
3032 
3033         }
3034         else
3035         {
3036             m_sr_module->clock_enable();  // turn on clock
3037         }
3038     }
3039 
3040     m_sr_module->update();
3041 }
3042 
3043 
3044 class SRinSink : public SignalSink
3045 {
3046 public:
SRinSink(SR_MODULE * _sr_module)3047     explicit SRinSink(SR_MODULE *_sr_module)
3048         : sr_module(_sr_module)
3049     {}
3050 
setSinkState(char new3State)3051     virtual void setSinkState(char new3State)
3052     {
3053         sr_module->setState(new3State);
3054     }
release()3055     virtual void release()
3056     {
3057         delete this;
3058     }
3059 private:
3060     SR_MODULE *sr_module;
3061 };
3062 
3063 
3064 class SRnSource : public PeripheralSignalSource
3065 {
3066 public:
SRnSource(PinModule * _pin,SR_MODULE * _sr_module,int _index)3067     SRnSource(PinModule *_pin, SR_MODULE *_sr_module, int _index) :
3068         PeripheralSignalSource(_pin), sr_module(_sr_module),
3069         index(_index)
3070     {}
release()3071     virtual void release()
3072     {
3073         sr_module->releasePin(index);
3074     }
3075 private:
3076     SR_MODULE *sr_module;
3077     int       index;
3078 };
3079 
3080 
3081 enum
3082 {
3083     SRQ = 0,
3084     SRNQ
3085 };
3086 
SR_MODULE(Processor * _cpu)3087 SR_MODULE::SR_MODULE(Processor *_cpu) :
3088     srcon0(_cpu, "srcon0", "SR Latch Control 0 Register", this),
3089     srcon1(_cpu, "srcon1", "SR Latch Control 1 Register", this),
3090     cpu(_cpu)
3091 {
3092 }
3093 
3094 
~SR_MODULE()3095 SR_MODULE::~SR_MODULE()
3096 {
3097     if (m_SRQsource_active)
3098     {
3099         SRQ_pin->setSource(0);
3100     }
3101 
3102     delete  m_SRQsource;
3103 
3104     if (m_SRNQsource_active)
3105     {
3106         SRNQ_pin->setSource(0);
3107     }
3108 
3109     delete  m_SRNQsource;
3110 }
3111 
3112 
3113 // determine output state of RS flip-flop
3114 // If both state_set and state_reset are true, Q output is 0
3115 // SPR[SP] and clocked inputs maybe set outside the update
3116 // function prior to its call.
update()3117 void SR_MODULE::update()
3118 {
3119     if ((srcon1.value.get() & SRCON1::SRSC1E) && syncc1out)
3120     {
3121         state_set = true;
3122     }
3123 
3124     if ((srcon1.value.get() & SRCON1::SRSC2E) && syncc2out)
3125     {
3126         state_set = true;
3127     }
3128 
3129     if ((srcon1.value.get() & SRCON1::SRSPE) && SRI_pin->getPin().getState())
3130     {
3131         state_set = true;
3132     }
3133 
3134     if ((srcon1.value.get() & SRCON1::SRRC1E) && syncc1out)
3135     {
3136         state_reset = true;
3137     }
3138 
3139     if ((srcon1.value.get() & SRCON1::SRRC2E) && syncc2out)
3140     {
3141         state_reset = true;
3142     }
3143 
3144     if ((srcon1.value.get() & SRCON1::SRRPE) && SRI_pin->getPin().getState())
3145     {
3146         state_reset = true;
3147     }
3148 
3149     if (state_set)
3150     {
3151         state_Q = true;
3152     }
3153 
3154     // reset overrides a set
3155     if (state_reset)
3156     {
3157         state_Q = false;
3158     }
3159 
3160     state_set = state_reset = false;
3161 
3162     if (!(srcon0.value.get() & SRCON0::SRLEN))
3163     {
3164         return;
3165     }
3166 
3167     if ((srcon0.value.get() & SRCON0::SRQEN))
3168     {
3169         m_SRQsource->putState(state_Q ? '1' : '0');
3170     }
3171 
3172     if ((srcon0.value.get() & SRCON0::SRNQEN))
3173     {
3174         m_SRNQsource->putState(!state_Q ? '1' : '0');
3175     }
3176 }
3177 
3178 
3179 // Stop clock if currently running
clock_disable()3180 void SR_MODULE::clock_disable()
3181 {
3182     if (future_cycle > get_cycles().get())
3183     {
3184         get_cycles().clear_break(this);
3185         future_cycle = 0;
3186     }
3187 
3188     future_cycle = 0;
3189 }
3190 
3191 
3192 // Start clock if not running
3193 // As break works on instruction cycles, clock runs every 1-128
3194 // instructions which is 1 << srclk
3195 //
clock_enable()3196 void SR_MODULE::clock_enable()
3197 {
3198     if (!future_cycle)
3199     {
3200         future_cycle = get_cycles().get() + (1 << srclk);
3201         get_cycles().set_break(future_cycle, this);
3202     }
3203 }
3204 
3205 
3206 // Called for clock rate change
clock_diff(unsigned int _srclk)3207 void SR_MODULE::clock_diff(unsigned int _srclk)
3208 {
3209     srclk = _srclk;
3210     clock_disable();
3211 
3212     if (srcon1.value.get() & (SRCON1::SRSCKE | SRCON1::SRRCKE))
3213     {
3214         clock_enable();
3215     }
3216 }
3217 
3218 
callback()3219 void SR_MODULE::callback()
3220 {
3221     bool active = false;
3222 
3223     if (srcon1.value.get() & (SRCON1::SRSCKE))   //Set clock enabled
3224     {
3225         active = true;
3226         pulse_set();
3227     }
3228 
3229     if (srcon1.value.get() & (SRCON1::SRRCKE))   //Reset clock enabled
3230     {
3231         active = true;
3232         pulse_reset();
3233     }
3234 
3235     if (active)
3236     {
3237         future_cycle = 0;
3238         clock_enable();
3239     }
3240 
3241     update();
3242 }
3243 
3244 
setPins(PinModule * sri,PinModule * srq,PinModule * srnq)3245 void SR_MODULE::setPins(PinModule *sri, PinModule *srq, PinModule *srnq)
3246 {
3247     if (!SRI_pin)
3248     {
3249         m_SRinSink = new SRinSink(this);
3250         sri->addSink(m_SRinSink);
3251 
3252     }
3253     else if (SRI_pin != sri)
3254     {
3255         SRI_pin->removeSink(m_SRinSink);
3256         sri->addSink(m_SRinSink);
3257     }
3258 
3259     SRI_pin = sri;
3260     SRQ_pin = srq;
3261     SRNQ_pin = srnq;
3262 }
3263 
3264 
3265 // If pin chnages and we are looking at it, call update
setState(char)3266 void SR_MODULE::setState(char /* IOin */ )
3267 {
3268     if (srcon1.value.get() & (SRCON1::SRSPE | SRCON1::SRRPE))
3269     {
3270         update();
3271     }
3272 }
3273 
3274 
syncC1out(bool val)3275 void SR_MODULE::syncC1out(bool val)
3276 {
3277     if (syncc1out != val)
3278     {
3279         syncc1out = val;
3280 
3281         if (srcon1.value.get() & (SRCON1::SRSC1E | SRCON1::SRRC1E))
3282         {
3283             update();
3284         }
3285     }
3286 }
3287 
3288 
syncC2out(bool val)3289 void SR_MODULE::syncC2out(bool val)
3290 {
3291     if (syncc2out != val)
3292     {
3293         syncc2out = val;
3294 
3295         if (srcon1.value.get() & (SRCON1::SRSC2E | SRCON1::SRRC2E))
3296         {
3297             update();
3298         }
3299     }
3300 }
3301 
3302 
3303 // Setup or tear down RSQ output pin
3304 // This is only call if SRLEN OR SRQEN has changed
Qoutput()3305 void SR_MODULE::Qoutput()
3306 {
3307     if ((srcon0.value.get() & (SRCON0::SRLEN | SRCON0::SRQEN)) ==
3308             (SRCON0::SRLEN | SRCON0::SRQEN))
3309     {
3310         if (!m_SRQsource)
3311         {
3312             m_SRQsource = new SRnSource(SRQ_pin, this, SRQ);
3313         }
3314 
3315         SRQ_pin->setSource(m_SRQsource);
3316         SRQ_pin->getPin().newGUIname("SRQ");
3317         m_SRQsource_active = true;
3318 
3319     }
3320     else
3321     {
3322         SRQ_pin->setSource(0);
3323 
3324         if (strcmp("SRQ", SRQ_pin->getPin().GUIname().c_str()) == 0)
3325         {
3326             SRQ_pin->getPin().newGUIname(SRQ_pin->getPin().name().c_str());
3327         }
3328     }
3329 }
3330 
3331 
3332 // Setup or tear down RSNQ output pin
3333 // This is only call if SRLEN OR SRNQEN has changed
NQoutput()3334 void SR_MODULE::NQoutput()
3335 {
3336     if ((srcon0.value.get() & (SRCON0::SRLEN | SRCON0::SRNQEN)) ==
3337             (SRCON0::SRLEN | SRCON0::SRNQEN))
3338     {
3339         if (!m_SRNQsource)
3340         {
3341             m_SRNQsource = new SRnSource(SRNQ_pin, this, SRNQ);
3342         }
3343 
3344         SRNQ_pin->setSource(m_SRNQsource);
3345         SRNQ_pin->getPin().newGUIname("SRNQ");
3346         m_SRNQsource_active = true;
3347 
3348     }
3349     else
3350     {
3351         SRNQ_pin->setSource(0);
3352 
3353         if (strcmp("SRNQ", SRNQ_pin->getPin().GUIname().c_str()) == 0)
3354         {
3355             SRNQ_pin->getPin().newGUIname(SRNQ_pin->getPin().name().c_str());
3356         }
3357     }
3358 }
3359 
3360 
releasePin(int index)3361 void SR_MODULE::releasePin(int index)
3362 {
3363     switch (index)
3364     {
3365     case SRQ:
3366         m_SRQsource_active = false;
3367         break;
3368 
3369     case SRNQ:
3370         m_SRNQsource_active = false;
3371         break;
3372     }
3373 }
3374 
3375 
3376 //-------------------------------------------------------------------
LVDCON_14(Processor * pCpu,const char * pName,const char * pDesc)3377 LVDCON_14::LVDCON_14(Processor *pCpu, const char *pName, const char *pDesc)
3378     : sfr_register(pCpu, pName, pDesc)
3379 {
3380 }
3381 
3382 
3383 double ldv_volts[] = {1.9, 2.0, 2.1, 2.2, 2.3, 4.0, 4.2, 4.5};
3384 
3385 
check_lvd()3386 void LVDCON_14::check_lvd()
3387 {
3388     unsigned int reg = value.get();
3389 
3390     if (!(reg & IRVST))
3391     {
3392         return;
3393     }
3394 
3395     double voltage = ldv_volts[reg & (LVDL0 | LVDL1 | LVDL2)];
3396     Processor *Cpu = (Processor *)cpu;
3397 
3398     if (Cpu->get_Vdd() <= voltage)
3399     {
3400         IntSrc->Trigger();
3401     }
3402 }
3403 
3404 
callback()3405 void LVDCON_14::callback()
3406 {
3407     value.put(value.get() | IRVST);
3408     check_lvd();
3409 }
3410 
3411 
put(unsigned int new_value)3412 void LVDCON_14::put(unsigned int new_value)
3413 {
3414     new_value &= write_mask;
3415     unsigned int diff = value.get() ^ new_value;
3416 
3417     if (!diff)
3418     {
3419         return;
3420     }
3421 
3422     trace.raw(write_trace.get() | value.get());
3423     value.put(new_value);
3424 
3425     if ((diff & LVDEN) && (new_value & LVDEN))   // Turning on
3426     {
3427         // wait before doing anything
3428         get_cycles().set_break(
3429             get_cycles().get() + 50e-6 * get_cycles().instruction_cps(),
3430             this);
3431     }
3432 
3433     return;
3434 }
3435 
3436