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