1 /*
2    Copyright (C) 1998 T. Scott Dattalo
3    Copyright (C) 2009,2013 Roy R. Rankin
4 
5 
6 This file is part of the libgpsim library of gpsim
7 
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12 
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 Lesser General Public License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, see
20 <http://www.gnu.org/licenses/lgpl-2.1.html>.
21 */
22 
23 #include <assert.h>
24 #include <stdio.h>
25 #include <iostream>
26 #include <string>
27 
28 #include "../config.h"
29 #include "14bit-processors.h"
30 #include "breakpoints.h"
31 #include "pic-ioports.h"
32 #include "pic-registers.h"
33 #include "ui.h"
34 
35 //#define DEBUG
36 #if defined(DEBUG)
37 #define Dprintf(arg) {printf("0x%06" PRINTF_GINT64_MODIFIER "X %s() ",cycles.get(),__FUNCTION__); printf arg; }
38 #else
39 #define Dprintf(arg) {}
40 #endif
41 
42 
43 //========================================================================
44 // Generic Configuration word for the midrange family.
45 
46 class Generic14bitConfigWord : public ConfigWord
47 {
48 public:
Generic14bitConfigWord(_14bit_processor * pCpu)49     explicit Generic14bitConfigWord(_14bit_processor *pCpu)
50         : ConfigWord("CONFIG", 0x3fff, "Configuration Word", pCpu, 0x2007)
51     {
52         assert(pCpu);
53         pCpu->wdt.initialize(true);
54     }
55 
56     enum
57     {
58         FOSC0  = 1 << 0,
59         FOSC1  = 1 << 1,
60         WDTEN  = 1 << 2,
61         PWRTEN = 1 << 3
62     };
63 
set(gint64 v)64     virtual void set(gint64 v)
65     {
66         gint64 oldV = getVal();
67         Integer::set(v);
68 
69         if (m_pCpu)
70         {
71             gint64 diff = oldV ^ v;
72 
73             if (diff & WDTEN)
74             {
75                 m_pCpu->wdt.initialize((v & WDTEN) == WDTEN);
76             }
77 
78             m_pCpu->config_modes->set_fosc01(v & (FOSC0 | FOSC1));
79             m_pCpu->config_modes->set_wdte((v & WDTEN) == WDTEN);
80             m_pCpu->config_modes->set_pwrte((v & PWRTEN) == PWRTEN);
81         }
82     }
83 
toString()84     virtual std::string toString()
85     {
86         gint64 i64;
87         get(i64);
88         int i = i64 & 0xfff;
89         char buff[256];
90         snprintf(buff, sizeof(buff),
91                  "$%3x\n"
92                  " FOSC=%d - Clk source = %s\n"
93                  " WDTEN=%d - WDT is %s\n"
94                  " PWRTEN=%d - Power up timer is %s\n",
95                  i,
96                  i & (FOSC0 | FOSC1),
97                  ((i & FOSC0) ? ((i & FOSC1) ? "EXTRC" : "XT") : ((i & FOSC1) ? "INTRC" : "LP")),
98                  ((i & WDTEN) ? 1 : 0), ((i & WDTEN) ? "enabled" : "disabled"),
99                  ((i & PWRTEN) ? 1 : 0), ((i & PWRTEN) ? "disabled" : "enabled"));
100         return buff;
101     }
102 };
103 
104 
105 //-------------------------------------------------------------------
_14bit_processor(const char * _name,const char * _desc)106 _14bit_processor::_14bit_processor(const char *_name, const char *_desc)
107     : pic_processor(_name, _desc)
108 {
109     pc = new Program_Counter("pc", "Program Counter", this);
110     pc->set_trace_command(); //trace.allocateTraceType(new PCTraceType(this,1)));
111     option_reg = new OPTION_REG(this, "option_reg");
112     stack = new Stack(this);
113 }
114 
115 
~_14bit_processor()116 _14bit_processor::~_14bit_processor()
117 {
118     unassignMCLRPin();
119     delete_sfr_register(fsr);
120     delete_sfr_register(option_reg);
121     delete pc;
122     pc = nullptr;
123 }
124 
125 
126 //-------------------------------------------------------------------
127 //
128 //
129 //    create
130 //
131 //  The purpose of this member function is to 'create' those things
132 // that are unique to the 14-bit core processors.
133 
create()134 void _14bit_processor :: create()
135 {
136     if (verbose)
137     {
138         std::cout << "_14bit_processor create, type = " << isa() << '\n';
139     }
140 
141     pic_processor::create();
142     fsr = new FSR(this, "fsr", "File Select Register for indirect addressing");
143 }
144 
145 
146 //-------------------------------------------------------------------
interrupt()147 void _14bit_processor::interrupt()
148 {
149     //bp.clear_interrupt();
150     intcon->in_interrupt = true;
151     bp.clear_interrupt();
152     stack->push(pc->value);
153     pc->interrupt(INTERRUPT_VECTOR);
154 }
155 
156 
157 //-------------------------------------------------------------------
save_state()158 void _14bit_processor::save_state()
159 {
160     pic_processor::save_state();
161     option_reg->put_trace_state(option_reg->value);
162 }
163 
164 
165 //-------------------------------------------------------------------
option_new_bits_6_7(unsigned int)166 void _14bit_processor::option_new_bits_6_7(unsigned int /* bits */ )
167 {
168     std::cout << "14bit, option bits 6 and/or 7 changed\n";
169 }
170 
171 
172 //-------------------------------------------------------------------
put_option_reg(unsigned int val)173 void _14bit_processor::put_option_reg(unsigned int val)
174 {
175     option_reg->put(val);
176 }
177 
178 
179 //------------------------------------------------------------------
180 // Fetch the rom contents at a particular address.
get_program_memory_at_address(unsigned int address)181 unsigned int _14bit_processor::get_program_memory_at_address(unsigned int address)
182 {
183     unsigned int uIndex = map_pm_address2index(address);
184 
185     if (uIndex < program_memory_size())
186     {
187         return  program_memory[uIndex] ? program_memory[uIndex]->get_opcode() : 0xffffffff;
188     }
189 
190     if (address >= 0x2000 && address < 0x2006)
191     {
192         return get_user_ids(address - 0x2000);
193     }
194 
195     if (uIndex == 0x2006)
196     {
197         return get_device_id();
198     }
199 
200     return get_config_word(address);
201 }
202 
203 
204 //-------------------------------------------------------------------
create_config_memory()205 void _14bit_processor::create_config_memory()
206 {
207     m_configMemory = new ConfigMemory(this, 1);
208     m_configMemory->addConfigWord(0, new Generic14bitConfigWord(this));
209 }
210 
211 
212 //-------------------------------------------------------------------
213 
set_config_word(unsigned int address,unsigned int cfg_word)214 bool _14bit_processor::set_config_word(unsigned int address, unsigned int cfg_word)
215 {
216     if ((address == config_word_address()) && config_modes)
217     {
218         config_word = cfg_word;
219         oscillator_select(cfg_word, false);
220 
221         if (m_configMemory && m_configMemory->getConfigWord(0))
222         {
223             m_configMemory->getConfigWord(0)->set((int)cfg_word);
224         }
225 
226         return true;
227     }
228 
229     return false;
230 }
231 
232 
233 // The working version of oscillator_select should be called at a higher level
234 // where the IO pins are defined
235 //
oscillator_select(unsigned int,bool)236 void _14bit_processor::oscillator_select(unsigned int /* mode */, bool /* not_clkout */ )
237 {
238     //    printf("Error _14bit_processor::oscillator_select called\n");
239 }
240 
241 
242 //-------------------------------------------------------------------
enter_sleep()243 void _14bit_processor::enter_sleep()
244 {
245     tmr0.sleep();
246     pic_processor::enter_sleep();
247 }
248 
249 
250 //-------------------------------------------------------------------
exit_sleep()251 void _14bit_processor::exit_sleep()
252 {
253     if (m_ActivityState == ePASleeping)
254     {
255         tmr0.wake();
256         pic_processor::exit_sleep();
257     }
258 }
259 
get_intedgx(int index)260 bool _14bit_processor::get_intedgx(int index)
261 {
262     return(option_reg->value.get() & OPTION_REG::INTEDG);
263 }
264 
265 
266 //-------------------------------------------------------------------
Pic14Bit(const char * _name,const char * _desc)267 Pic14Bit::Pic14Bit(const char *_name, const char *_desc)
268     : _14bit_processor(_name, _desc),
269       intcon_reg(this, "intcon", "Interrupt Control"),
270       int_pin(this, &intcon_reg, 0)
271 {
272     m_porta = new PicPortRegister(this, "porta", "", 8, 0x1f);
273     m_trisa = new PicTrisRegister(this, "trisa", "", m_porta, false);
274     tmr0.set_cpu(this, m_porta, 4, option_reg);
275     tmr0.start(0);
276     m_portb = new PicPortBRegister(this, "portb", "", &intcon_reg, 8, 0xff);
277     m_trisb = new PicTrisRegister(this, "trisb", "", m_portb, false);
278 }
279 
280 
281 //-------------------------------------------------------------------
~Pic14Bit()282 Pic14Bit::~Pic14Bit()
283 {
284     unassignMCLRPin();
285     remove_sfr_register(&tmr0);
286     remove_sfr_register(&intcon_reg);
287     delete_sfr_register(m_portb);
288     delete_sfr_register(m_trisb);
289     delete_sfr_register(m_porta);
290     delete_sfr_register(m_trisa);
291 }
292 
293 
294 //-------------------------------------------------------------------
create_symbols()295 void Pic14Bit::create_symbols()
296 {
297     pic_processor::create_symbols();
298     addSymbol(Wreg);
299 }
300 
301 
302 //-------------------------------------------------------------------
create_sfr_map()303 void Pic14Bit::create_sfr_map()
304 {
305     add_sfr_register(indf,    0x00);
306     alias_file_registers(0x00, 0x00, 0x80);
307     add_sfr_register(&tmr0,   0x01);
308     add_sfr_register(option_reg,  0x81, RegisterValue(0xff, 0));
309     add_sfr_register(pcl,     0x02, RegisterValue(0, 0));
310     add_sfr_register(status,  0x03, RegisterValue(0x18, 0));
311     add_sfr_register(fsr,     0x04);
312     alias_file_registers(0x02, 0x04, 0x80);
313     add_sfr_register(m_porta, 0x05);
314     add_sfr_register(m_trisa, 0x85, RegisterValue(0x3f, 0));
315     add_sfr_register(m_portb, 0x06);
316     add_sfr_register(m_trisb, 0x86, RegisterValue(0xff, 0));
317     add_sfr_register(pclath,  0x0a, RegisterValue(0, 0));
318     //add_sfr_register(pclath,  0x8a, RegisterValue(0,0));
319     add_sfr_register(&intcon_reg, 0x0b, RegisterValue(0, 0));
320     //add_sfr_register(&intcon_reg, 0x8b, RegisterValue(0,0));
321     alias_file_registers(0x0a, 0x0b, 0x80);
322     intcon = &intcon_reg;
323 }
324 
325 
326 //-------------------------------------------------------------------
option_new_bits_6_7(unsigned int bits)327 void Pic14Bit::option_new_bits_6_7(unsigned int bits)
328 {
329     //1 ((PORTB *)portb)->rbpu_intedg_update(bits);
330     m_portb->setRBPU((bits & (1 << 7)) == (1 << 7));
331     m_portb->setIntEdge((bits & (1 << 6)) == (1 << 6));
332 }
333 
334 
_14bit_e_processor(const char * _name,const char * _desc)335 _14bit_e_processor::_14bit_e_processor(const char *_name, const char *_desc)
336     : _14bit_processor(_name, _desc),
337       mclr_pin(4),
338       intcon_reg(this, "intcon", "Interrupt Control"),
339       bsr(this, "bsr", "Bank Select Register"),
340       pcon(this, "pcon", "Power Control Register", 0xcf),
341       wdtcon(this, "wdtcon", "WDT Control", 0x3f),
342       ind0(this, std::string("0")),
343       ind1(this, std::string("1")),
344       status_shad(this, "status_shad", "Status shadow register"),
345       wreg_shad(this, "wreg_shad", "wreg shadow register"),
346       bsr_shad(this, "bsr_shad", "bsr shadow register"),
347       pclath_shad(this, "pclath_shad", "pclath shadow register"),
348       fsr0l_shad(this, "fsr0l_shad", "fsr0l shadow register"),
349       fsr0h_shad(this, "fsr0h_shad", "fsr0h shadow register"),
350       fsr1l_shad(this, "fsr1l_shad", "fsr1l shadow register"),
351       fsr1h_shad(this, "fsr1h_shad", "fsr1h shadow register"),
352       int_pin(this, &intcon_reg, 0)
353 {
354     delete option_reg;
355     option_reg = new OPTION_REG_2(this, "option_reg", "Option Register");
356     delete stack;
357     stack = new Stack14E(this);
358     stack->stack_mask = 0xf; // ehanced has stack 16 high
359     intcon = &intcon_reg;
360 }
361 
362 
~_14bit_e_processor()363 _14bit_e_processor::~_14bit_e_processor()
364 {
365     remove_sfr_register(&ind0.indf);
366     remove_sfr_register(&ind1.indf);
367     remove_sfr_register(&ind0.fsrl);
368     remove_sfr_register(&ind0.fsrh);
369     remove_sfr_register(&ind1.fsrl);
370     remove_sfr_register(&ind1.fsrh);
371     remove_sfr_register(&bsr);
372     remove_sfr_register(&intcon_reg);
373     remove_sfr_register(&pcon);
374     remove_sfr_register(&wdtcon);
375     // These are copies taken at an interrupt
376     remove_sfr_register(&status_shad);
377     remove_sfr_register(&wreg_shad);
378     remove_sfr_register(&bsr_shad);
379     remove_sfr_register(&pclath_shad);
380     remove_sfr_register(&fsr0l_shad);
381     remove_sfr_register(&fsr0h_shad);
382     remove_sfr_register(&fsr1l_shad);
383     remove_sfr_register(&fsr1h_shad);
384     Stack14E *stack14E = static_cast<Stack14E *>(stack);
385     remove_sfr_register(&stack14E->stkptr);
386     remove_sfr_register(&stack14E->tosl);
387     remove_sfr_register(&stack14E->tosh);
388 }
389 
390 
create_symbols()391 void _14bit_e_processor::create_symbols()
392 {
393     pic_processor::create_symbols();
394     addSymbol(Wreg);
395 }
396 
397 
create_sfr_map()398 void _14bit_e_processor::create_sfr_map()
399 {
400     int bank;
401     add_sfr_register(&ind0.indf,  0x00, RegisterValue(0, 0), "indf0");
402     add_sfr_register(&ind1.indf,  0x01, RegisterValue(0, 0), "indf1");
403     add_sfr_register(pcl,     0x02, RegisterValue(0, 0));
404     add_sfr_register(status,  0x03, RegisterValue(0x18, 0));
405     add_sfr_register(&ind0.fsrl,  0x04, RegisterValue(0, 0), "fsr0l");
406     add_sfr_registerR(&ind0.fsrh,  0x05, RegisterValue(0, 0), "fsr0h");
407     add_sfr_register(&ind1.fsrl,  0x06, RegisterValue(0, 0), "fsr1l");
408     add_sfr_registerR(&ind1.fsrh,  0x07, RegisterValue(0, 0), "fsr1h");
409     add_sfr_register(&bsr,     0x08);
410     add_sfr_register(Wreg,     0x09);
411     add_sfr_register(pclath,  0x0a, RegisterValue(0, 0));
412     add_sfr_registerR(&intcon_reg, 0x0b, RegisterValue(0, 0));
413     add_sfr_register(&pcon,   0x96, RegisterValue(0x0c, 0), "pcon");
414     wdt.set_postscale(0);
415     wdt.set_timeout(1.0 / 32000.0);
416     add_sfr_registerR(&wdtcon,   0x97, RegisterValue(0x16, 0), "wdtcon");
417     // These are copies taken at an interrupt
418     add_sfr_register(&status_shad,  0xfe4);
419     add_sfr_register(&wreg_shad,    0xfe5);
420     add_sfr_register(&bsr_shad,     0xfe6);
421     add_sfr_register(&pclath_shad,  0xfe7);
422     add_sfr_register(&fsr0l_shad,   0xfe8);
423     add_sfr_register(&fsr0h_shad,   0xfe9);
424     add_sfr_register(&fsr1l_shad,   0xfea);
425     add_sfr_register(&fsr1h_shad,   0xfeb);
426     Stack14E *stack14E = static_cast<Stack14E *>(stack);
427     add_sfr_register(&stack14E->stkptr,  0xfed, RegisterValue(0, 0), "stkptr");
428     add_sfr_register(&stack14E->tosl,    0xfee, RegisterValue(0, 0), "tosl");
429     add_sfr_register(&stack14E->tosh,    0xfef, RegisterValue(0, 0), "tosh");
430 
431     for (bank = 1; bank < 32; bank++)
432     {
433         alias_file_registers(0x00, 0x0b, bank * 0x80); // Duplicate core registers
434         alias_file_registers(0x70, 0x7f, bank * 0x80); // Duplicate shadow ram
435     }
436 
437     stack->stack_mask = 15; // enhanced has stack 16 high
438 }
439 
440 
441 //-------------------------------------------------------------------
442 //	Similar to pic_processoer version except sets PCON flags
443 //
reset(RESET_TYPE r)444 void _14bit_e_processor::reset(RESET_TYPE r)
445 {
446     switch (r)
447     {
448     case POR_RESET:
449         pcon.put(0x0d);
450         break;
451 
452     case SOFT_RESET:
453         pcon.put(pcon.get() & ~PCON::RI);
454         break;
455 
456     case MCLR_RESET:
457         std::cout << "Reset due to MCLR\n";
458         pcon.put(pcon.get() & ~PCON::RMCLR);
459         break;
460 
461     case STKOVF_RESET:
462         pcon.put(pcon.get() | PCON::STKOVF);
463         break;
464 
465     case STKUNF_RESET:
466         pcon.put(pcon.get() | PCON::STKUNF);
467         break;
468 
469     default:
470         break;
471     };
472 
473     pic_processor::reset(r);
474 }
475 
476 
477 //-------------------------------------------------------------------
478 // The enhanced processors save a number of registers into
479 // their shadow registers on interrupt
480 //
interrupt()481 void _14bit_e_processor::interrupt()
482 {
483     bp.clear_interrupt();
484 
485     if (bp.have_sleep())
486     {
487         bp.clear_sleep();
488         stack->push(pc->value + 1);
489 
490     }
491     else
492     {
493         stack->push(pc->value);
494     }
495 
496     status_shad.value = status->value;
497     wreg_shad.value = Wreg->value;
498     bsr_shad.value = bsr.value;
499     pclath_shad.value = pclath->value;
500     fsr0l_shad.value = ind0.fsrl.value;
501     fsr0h_shad.value = ind0.fsrh.value;
502     fsr1l_shad.value = ind1.fsrl.value;
503     fsr1h_shad.value = ind1.fsrh.value;
504     intcon->in_interrupt = true;
505     pc->interrupt(INTERRUPT_VECTOR);
506 }
507 
508 
509 //-------------------------------------------------------------------
enter_sleep()510 void _14bit_e_processor::enter_sleep()
511 {
512     tmr0.sleep();
513 
514     if (wdt_flag == 2)  	// WDT is suspended during sleep
515     {
516         wdt.initialize(false);
517     }
518 
519     pic_processor::enter_sleep();
520 }
521 
522 
523 //-------------------------------------------------------------------
exit_wdt_sleep()524 bool _14bit_e_processor::exit_wdt_sleep()
525 {
526     return true;
527 }
528 
529 
530 //-------------------------------------------------------------------
exit_sleep()531 void _14bit_e_processor::exit_sleep()
532 {
533     if (m_ActivityState == ePASleeping)
534     {
535         tmr0.wake();
536 
537         if (wdt_flag == 2)
538         {
539             wdt.initialize(true);
540         }
541 
542         pic_processor::exit_sleep();
543     }
544 }
545 
546 
547 //========================================================================
548 //
549 // Configuration Memory word 1for the enhanced 14 bit processors
550 
551 class Config_E : public ConfigWord
552 {
553 public:
Config_E(_14bit_e_processor * pCpu,const char * name,unsigned int address,bool EEw=false)554     Config_E(_14bit_e_processor *pCpu, const char *name, unsigned int address, bool EEw = false)
555         : ConfigWord(name, 0x3fff, "Configuration Word", pCpu, address, EEw)
556     {
557         if (m_pCpu)
558         {
559             m_pCpu->set_config_word(address, 0x3fff);
560         }
561     }
562 };
563 
564 
create_config_memory()565 void _14bit_e_processor::create_config_memory()
566 {
567     m_configMemory = new ConfigMemory(this, 9);
568     m_configMemory->addConfigWord(0, new Config_E(this, "UserID1", 0x8000, true));
569     m_configMemory->addConfigWord(1, new Config_E(this, "UserID2", 0x8001, true));
570     m_configMemory->addConfigWord(2, new Config_E(this, "UserID3", 0x8002, true));
571     m_configMemory->addConfigWord(3, new Config_E(this, "UserID4", 0x8003, true));
572     m_configMemory->addConfigWord(6, new Config_E(this, "DeviceID", 0x8006));
573     m_configMemory->addConfigWord(7, new Config_E(this, "ConfigW1", 0x8007));
574     m_configMemory->addConfigWord(8, new Config_E(this, "ConfigW2", 0x8008));
575 }
576 
577 
set_config_word(unsigned int address,unsigned int cfg_word)578 bool _14bit_e_processor::set_config_word(unsigned int address, unsigned int cfg_word)
579 {
580     enum
581     {
582         FOSC0  = 1 << 0,
583         FOSC1  = 1 << 1,
584         FOSC2  = 1 << 2,
585         WDTEN0 = 1 << 3,
586         WDTEN1 = 1 << 4,
587         PWRTEN = 1 << 5,
588         MCLRE  = 1 << 6,
589         CP     = 1 << 7,
590         CPD    = 1 << 8,
591         BOREN0 = 1 << 9,
592         BOREN1 = 1 << 10,
593         NOT_CLKOUTEN = 1 << 11,
594         //    IESO   = 1<<12,
595         // Config word 2
596         WRT0   = 1 << 0,
597         WRT1   = 1 << 1,
598         PPS1WAY = 1 << 2,
599         ZCDDIS = 1 << 7,
600         PLLEN  = 1 << 8,
601         STVREN = 1 << 9,
602     };
603 
604     Dprintf((" add %x word %x\n", address, cfg_word));
605 
606     if (address == 0x8007)   // Config Word 1
607     {
608         wdt_flag = (cfg_word & (WDTEN0 | WDTEN1)) >> 3;
609         Dprintf((" cfg_word %x MCLRE %x\n", cfg_word, cfg_word & MCLRE));
610 
611         if ((cfg_word & MCLRE) == MCLRE)
612         {
613             assignMCLRPin(mclr_pin);
614 
615         }
616         else
617         {
618             unassignMCLRPin();
619         }
620         set_pps1way(cfg_word & PPS1WAY);
621 
622         wdt.initialize(wdt_flag & 2);
623         oscillator_select(cfg_word, (cfg_word & NOT_CLKOUTEN) != NOT_CLKOUTEN);
624 
625     }
626     else if (address == 0x8008)
627     {
628         // stack over/under reset flag
629         stack->STVREN = ((cfg_word & STVREN) == STVREN);
630         Dprintf((" STVREN %x flag %d\n", cfg_word & STVREN, stack->STVREN));
631         // Program memory write protect (eeprom)
632         program_memory_wp(cfg_word & (WRT1 | WRT0));
633         set_pplx4_osc(cfg_word & PLLEN);
634         Dprintf((" ZCDDIS=%x\n", cfg_word & ZCDDIS));
635         set_zcddis(cfg_word & ZCDDIS);
636     }
637 
638     return pic_processor::set_config_word(address, cfg_word);
639 }
640 
641 
642 // The working version of oscillator_select should be called at a higher level
643 // where the IO pins are defined
644 //
oscillator_select(unsigned int,bool)645 void _14bit_e_processor::oscillator_select(unsigned int /* mode */, bool /* not_clkout */ )
646 {
647     printf("Error _14bit_e_processor::oscillator_select called\n");
648 }
649 
650 
651 // The working version of program_memory_wp should be called at a higher level
652 // where the eeprom is defined
653 //
program_memory_wp(unsigned int)654 void _14bit_e_processor::program_memory_wp(unsigned int /* mode */ )
655 {
656     printf("Error _14bit_e_processor::program_memory_wp called\n");
657 }
658 
659 
660 // This function routes Wreg put requests through registers (if possible)
661 // for breaking and logging
Wput(unsigned int value)662 void _14bit_e_processor::Wput(unsigned int value)
663 {
664     if (Wreg->address)
665     {
666         registers[Wreg->address]->put(value);
667 
668     }
669     else
670     {
671         Wreg->put(value);
672     }
673 }
674 
675 
676 // This function routes Wreg get requests through registers (if possible)
677 // for breaking and logging
Wget()678 unsigned int _14bit_e_processor::Wget()
679 {
680     if (Wreg->address)
681     {
682         return registers[Wreg->address]->get();
683 
684     }
685     else
686     {
687         return Wreg->get();
688     }
689 }
690 
691