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