1 /*
2 * Simulator of microcontrollers (uc.cc)
3 *
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5 *
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7 *
8 */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING. If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include "i_string.h"
35
36 // prj
37 #include "globals.h"
38 #include "utils.h"
39
40 // cmd.src
41 #include "newcmdcl.h"
42 #include "cmdutil.h"
43 #include "cmd_uccl.h"
44 #include "cmd_bpcl.h"
45 #include "cmd_getcl.h"
46 #include "cmd_setcl.h"
47 #include "cmd_infocl.h"
48 #include "cmd_timercl.h"
49 #include "cmd_statcl.h"
50 #include "cmd_memcl.h"
51
52 // local, sim.src
53 #include "uccl.h"
54 #include "hwcl.h"
55 #include "memcl.h"
56 #include "simcl.h"
57 #include "itsrccl.h"
58 #include "simifcl.h"
59 #include "vcdcl.h"
60
61
62 static class cl_uc_error_registry uc_error_registry;
63
64 /*
65 * Clock counter
66 */
67
cl_ticker(int adir,int in_isr,const char * aname)68 cl_ticker::cl_ticker(int adir, int in_isr, const char *aname)
69 {
70 options= TICK_RUN;
71 if (in_isr)
72 options|= TICK_INISR;
73 dir= adir;
74 ticks= 0;
75 set_name(aname);
76 }
77
~cl_ticker(void)78 cl_ticker::~cl_ticker(void) {}
79
80 int
tick(int nr)81 cl_ticker::tick(int nr)
82 {
83 if (options&TICK_RUN)
84 ticks+= dir*nr;
85 return(ticks);
86 }
87
88 double
get_rtime(double xtal)89 cl_ticker::get_rtime(double xtal)
90 {
91 double d;
92
93 d= (double)ticks/xtal;
94 return(d);
95 }
96
97 void
dump(int nr,double xtal,class cl_console_base * con)98 cl_ticker::dump(int nr, double xtal, class cl_console_base *con)
99 {
100 con->dd_printf("timer #%d(\"%s\") %s%s: %g sec (%lu clks)\n",
101 nr, get_name("unnamed"),
102 (options&TICK_RUN)?"ON":"OFF",
103 (options&TICK_INISR)?",ISR":"",
104 get_rtime(xtal), ticks);
105 }
106
107
108 /*
109 * Options of uc
110 */
111
cl_xtal_option(class cl_uc * the_uc)112 cl_xtal_option::cl_xtal_option(class cl_uc *the_uc):
113 cl_optref(the_uc)
114 {
115 uc= the_uc;
116 }
117
118 void
option_changed(void)119 cl_xtal_option::option_changed(void)
120 {
121 if (!uc)
122 return;
123 double d;
124 option->get_value(&d);
125 uc->xtal= d;
126 }
127
128
129 /* Time measurer */
130
cl_time_measurer(class cl_uc * the_uc)131 cl_time_measurer::cl_time_measurer(class cl_uc *the_uc):
132 cl_base()
133 {
134 to_reach= 0;
135 uc= the_uc;
136 }
137
138 void
set_reach(unsigned long val)139 cl_time_measurer::set_reach(unsigned long val)
140 {
141 to_reach= val;
142 }
143
144 void
from_now(unsigned long val)145 cl_time_measurer::from_now(unsigned long val)
146 {
147 set_reach(now() + val);
148 }
149
150 bool
reached()151 cl_time_measurer::reached()
152 {
153 return to_reach &&
154 (now() >= to_reach);
155 }
156
157 unsigned long
now()158 cl_time_measurer::now()
159 {
160 return 0;
161 }
162
163
164 /* value of xtal clock */
165
166 unsigned long
now()167 cl_time_clk::now()
168 {
169 if (!uc) return 0;
170 return uc->ticks->ticks;
171 }
172
173
174 /* value of virtual clocks */
175
176 unsigned long
now()177 cl_time_vclk::now()
178 {
179 if (!uc) return 0;
180 return uc->vc.fetch + uc->vc.rd + uc->vc.wr;
181 }
182
183
184 /* value of fetches */
185
186 unsigned long
now()187 cl_time_fclk::now()
188 {
189 if (!uc) return 0;
190 return uc->vc.fetch;
191 }
192
193
194 /* value of reads */
195
196 unsigned long
now()197 cl_time_rclk::now()
198 {
199 if (!uc) return 0;
200 return uc->vc.rd;
201 }
202
203
204 /* value of writes */
205
206 unsigned long
now()207 cl_time_wclk::now()
208 {
209 if (!uc) return 0;
210 return uc->vc.wr;
211 }
212
213
214 /* OMF file record */
215
cl_omf_rec(void)216 cl_omf_rec::cl_omf_rec(void):
217 cl_base()
218 {
219 offset= 0;
220 f_offset= 0;
221 type= 0;
222 len= 0;
223 rec= NULL;
224 chk= 0;
225 }
226
~cl_omf_rec(void)227 cl_omf_rec::~cl_omf_rec(void)
228 {
229 if (rec)
230 free(rec);
231 }
232
233 unsigned char
g(cl_f * f)234 cl_omf_rec::g(cl_f *f)
235 {
236 unsigned char c= f->get_c();
237 offset++;
238 return c;
239 }
240
241 u16_t
pick_word(int i)242 cl_omf_rec::pick_word(int i)
243 {
244 unsigned char h, l;
245 u16_t w;
246
247 if (i >= len-1)
248 return 0;
249 l= rec[i];
250 h= rec[i+1];
251 w= h*256+l;
252 return w;
253 }
254
255 chars
pick_str(int i)256 cl_omf_rec::pick_str(int i)
257 {
258 unsigned char l, j;
259 chars s= "";
260
261 if (i >= len-1)
262 return chars("");
263 l= rec[i];
264 j= 0;
265 while (l &&
266 (i < len))
267 {
268 s+= rec[i+1+j];
269 l--;
270 j++;
271 }
272 return s;
273 }
274
275 bool
read(cl_f * f)276 cl_omf_rec::read(cl_f *f)
277 {
278 unsigned char c;
279 int i, l, h;
280
281 if (rec)
282 {
283 free(rec);
284 rec= NULL;
285 }
286 f_offset= offset;
287 if (f->eof())
288 return false;
289 c= g(f);
290 type= c;
291 if (f->eof())
292 return false;
293 c= g(f);
294 l= c;
295 //printf("l=%02x\n", c);
296 if (f->eof())
297 return false;
298 c= g(f);
299 h= c;
300 //printf("h=%02x\n", c);
301 if (f->eof())
302 return false;
303 len= h*256+l-1;
304 rec= (u8_t*)malloc(len);
305 for (i= 0; i < len; i++)
306 {
307 rec[i]= g(f);
308 if (f->eof())
309 return false;
310 }
311 chk= g(f);
312
313 return true;
314 }
315
316
317 /*
318 * Abstract microcontroller
319 ******************************************************************************
320 */
321
cl_uc(class cl_sim * asim)322 cl_uc::cl_uc(class cl_sim *asim):
323 cl_base()
324 {
325 type= NULL;
326 //int i;
327 sim = asim;
328 //mems= new cl_list(MEM_TYPES, 1);
329 memchips= new cl_list(2, 2, "memchips");
330 address_spaces= new cl_address_space_list(this);
331 //address_decoders= new cl_list(2, 2);
332 rom= 0;
333
334 hws = new cl_hws();
335 //options= new cl_list(2, 2);
336 //for (i= MEM_ROM; i < MEM_TYPES; i++) mems->add(0);
337 xtal_option= new cl_xtal_option(this);
338 xtal_option->init();
339 ticks= new cl_ticker(+1, 0, "time");
340 isr_ticks= new cl_ticker(+1, TICK_INISR, "isr");
341 idle_ticks= new cl_ticker(+1, TICK_IDLE, "idle");
342 counters= new cl_list(2, 2, "counters");
343 it_levels= new cl_list(2, 2, "it levels");
344 it_sources= new cl_irqs(2, 2);
345 class it_level *il= new it_level(-1, 0, 0, 0);
346 it_levels->push(il);
347 stack_ops= new cl_list(2, 2, "stack operations");
348 errors= new cl_list(2, 2, "errors in uc");
349 events= new cl_list(2, 2, "events in uc");
350 sp_max= 0;
351 sp_avg= 0;
352 inst_exec= false;
353 }
354
355
~cl_uc(void)356 cl_uc::~cl_uc(void)
357 {
358 //delete mems;
359 delete hws;
360 //delete options;
361 delete ticks;
362 delete isr_ticks;
363 delete idle_ticks;
364 delete counters;
365 events->disconn_all();
366 delete events;
367 delete fbrk;
368 delete ebrk;
369 delete it_levels;
370 delete it_sources;
371 delete stack_ops;
372 errors->free_all();
373 delete errors;
374 delete xtal_option;
375 delete address_spaces;
376 delete memchips;
377 //delete address_decoders;
378 }
379
380
381 int
init(void)382 cl_uc::init(void)
383 {
384 int i;
385
386 set_name("controller");
387 cl_base::init();
388 if (xtal_option->use("xtal"))
389 xtal= xtal_option->get_value(xtal);
390 else
391 xtal= 11059200;
392 vars= new cl_var_list();
393 make_variables();
394 make_memories();
395 if (rom == NULL)
396 rom= address_space(cchars("rom")/*MEM_ROM_ID*/);
397 ebrk= new brk_coll(2, 2, rom);
398 fbrk= new brk_coll(2, 2, rom);
399 fbrk->Duplicates= false;
400 brk_counter= 0;
401 stop_at_time= 0;
402 make_cpu_hw();
403 mk_hw_elements();
404 class cl_cmdset *cs= sim->app->get_commander()->cmdset;
405 build_cmdset(cs);
406 irq= false;
407 reset();
408
409 return 0;
410 for (i= 0; i < sim->app->in_files->count; i++)
411 {
412 char *fname= (char *)(sim->app->in_files->at(i));
413 long l;
414 if ((l= read_hex_file(fname)) >= 0)
415 {
416 /*sim->app->get_commander()->all_*/printf("%ld words read from %s\n",
417 l, fname);
418 }
419 }
420 return(0);
421 }
422
423 char *
id_string(void)424 cl_uc::id_string(void)
425 {
426 return((char*)"unknown microcontroller");
427 }
428
429 void
reset(void)430 cl_uc::reset(void)
431 {
432 class it_level *il;
433
434 irq= false;
435 instPC= PC= 0;
436 state = stGO;
437 ticks->ticks= 0;
438 isr_ticks->ticks= 0;
439 idle_ticks->ticks= 0;
440 vc.inst= vc.fetch= vc.rd= vc.wr= 0;
441 /*FIXME should we clear user counters?*/
442 il= (class it_level *)(it_levels->top());
443 while (il &&
444 il->level >= 0)
445 {
446 il= (class it_level *)(it_levels->pop());
447 delete il;
448 il= (class it_level *)(it_levels->top());
449 }
450 sp_max= 0;
451 sp_avg= 0;
452
453 stack_ops->free_all();
454
455 int i;
456 for (i= 0; i < hws->count; i++)
457 {
458 class cl_hw *hw= (class cl_hw *)(hws->at(i));
459 hw->reset();
460 }
461 }
462
463 /*
464 * Making elements
465 */
466
467 void
make_memories(void)468 cl_uc::make_memories(void)
469 {
470 }
471
472 void
make_variables(void)473 cl_uc::make_variables(void)
474 {
475 class cl_address_space *as;
476 class cl_option *o= sim->app->options->get_option("var_size");
477 long l, i;
478
479 if (o)
480 o->get_value(&l);
481 else
482 l= 0x100;
483
484 class cl_address_decoder *ad;
485 class cl_memory_chip *chip;
486
487 if (l > 0)
488 {
489 variables= as= new cl_address_space("variables", 0, l, 32);
490 as->init();
491 address_spaces->add(as);
492
493 chip= new cl_memory_chip("variable_storage", l, 32);
494 chip->init();
495 memchips->add(chip);
496 ad= new cl_address_decoder(variables, chip, 0, l-1, 0);
497 ad->init();
498 variables->decoders->add(ad);
499 ad->activate(0);
500
501 for (i= 0; i < l; i++)
502 variables->set(i, 0);
503 }
504 }
505
506 /*t_addr
507 cl_uc::get_mem_size(char *id)
508 {
509 class cl_memory *m= memory(id);
510 return(m?(m->get_size()):0);
511 }
512
513 int
514 cl_uc::get_mem_width(char *id)
515 {
516 class cl_memory *m= memory(id);
517 return(m?(m->width):8);
518 }
519 */
520 void
make_cpu_hw(void)521 cl_uc::make_cpu_hw(void)
522 {
523 cpu= NULL;
524 }
525
526 void
mk_hw_elements(void)527 cl_uc::mk_hw_elements(void)
528 {
529 class cl_hw *h;
530
531 add_hw(h= new cl_simulator_interface(this));
532 h->init();
533 add_hw(h= new cl_vcd(this, 0, "vcd"));
534 h->init();
535 }
536
537 void
build_cmdset(class cl_cmdset * cmdset)538 cl_uc::build_cmdset(class cl_cmdset *cmdset)
539 {
540 class cl_cmd *cmd;
541 class cl_super_cmd *super_cmd;
542 class cl_cmdset *cset;
543
544 cmdset->add(cmd= new cl_state_cmd("state", 0));
545 cmd->init();
546
547 #ifdef STATISTIC
548 cmdset->add(cmd= new cl_statistic_cmd("statistic", 0));
549 cmd->init();
550 #endif
551
552 cmdset->add(cmd= new cl_file_cmd("file", 0));
553 cmd->init();
554 cmd->add_name("load");
555
556 cmdset->add(cmd= new cl_dl_cmd("download", 0));
557 cmd->init();
558 cmd->add_name("dl");
559
560 cmdset->add(cmd= new cl_pc_cmd("pc", 0));
561 cmd->init();
562
563 cmdset->add(cmd= new cl_reset_cmd("reset", 0));
564 cmd->init();
565
566 cmdset->add(cmd= new cl_dump_cmd("dump", true));
567 cmd->init();
568
569 cmdset->add(cmd= new cl_dch_cmd("dch", true));
570 cmd->init();
571
572 cmdset->add(cmd= new cl_dc_cmd("dc", true));
573 cmd->init();
574
575 cmdset->add(cmd= new cl_disassemble_cmd("disassemble", true));
576 cmd->init();
577
578 cmdset->add(cmd= new cl_fill_cmd("fill", 0));
579 cmd->init();
580
581 cmdset->add(cmd= new cl_where_cmd("where", 0));
582 cmd->init();
583
584 cmdset->add(cmd= new cl_Where_cmd("Where", 0));
585 cmd->init();
586
587 cmdset->add(cmd= new cl_hole_cmd("hole", 0));
588 cmd->init();
589
590 cmdset->add(cmd= new cl_break_cmd("break", 0));
591 cmd->init();
592
593 cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0));
594 cmd->init();
595
596 cmdset->add(cmd= new cl_clear_cmd("clear", 0));
597 cmd->init();
598
599 cmdset->add(cmd= new cl_delete_cmd("delete", 0));
600 cmd->init();
601
602 cmdset->add(cmd= new cl_commands_cmd("commands", 0));
603 cmd->init();
604
605 {
606 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("get"));
607 if (super_cmd)
608 cset= super_cmd->commands;
609 else {
610 cset= new cl_cmdset();
611 cset->init();
612 }
613 cset->add(cmd= new cl_get_sfr_cmd("sfr", 0));
614 cmd->init();
615 /*cset->add(cmd= new cl_get_option_cmd("option", 0));
616 cmd->init();*/
617 }
618 if (!super_cmd)
619 {
620 cmdset->add(cmd= new cl_super_cmd("get", 0, cset));
621 cmd->init();
622 set_get_help(cmd);
623 }
624
625 {
626 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("set"));
627 if (super_cmd)
628 cset= super_cmd->commands;
629 else {
630 cset= new cl_cmdset();
631 cset->init();
632 }
633 cset->add(cmd= new cl_set_mem_cmd("memory", 0));
634 cmd->init();
635 cset->add(cmd= new cl_set_bit_cmd("bit", 0));
636 cmd->init();
637 cset->add(cmd= new cl_set_hw_cmd("hardware", 0));
638 cmd->add_name("hw");
639 cmd->init();
640 }
641 if (!super_cmd)
642 {
643 cmdset->add(cmd= new cl_super_cmd("set", 0, cset));
644 cmd->init();
645 set_set_help(cmd);
646 }
647
648 { // info
649 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("info"));
650 if (super_cmd)
651 cset= super_cmd->get_subcommands();
652 else {
653 cset= new cl_cmdset();
654 cset->init();
655 }
656 cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0));
657 cmd->add_name("bp");
658 cmd->init();
659 cset->add(cmd= new cl_info_reg_cmd("registers", 0));
660 cmd->init();
661 cset->add(cmd= new cl_info_hw_cmd("hardware", 0));
662 cmd->add_name("hw");
663 cmd->init();
664 /*
665 cset->add(cmd= new cl_info_stack_cmd("stack", 0,
666 "info stack Status of stack of the CPU",
667 "long help of info stack"));
668 cmd->init();
669 */
670 cset->add(cmd= new cl_info_memory_cmd("memory", 0));
671 cmd->init();
672 cset->add(cmd= new cl_info_var_cmd("variables", 0));
673 cmd->init();
674 cmd->add_name("vars");
675 }
676 if (!super_cmd) {
677 cmdset->add(cmd= new cl_super_cmd("info", 0, cset));
678 cmd->init();
679 set_info_help(cmd);
680 }
681
682 {
683 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("timer"));
684 if (super_cmd)
685 cset= super_cmd->get_subcommands();
686 else {
687 cset= new cl_cmdset();
688 cset->init();
689 }
690 cset->add(cmd= new cl_timer_add_cmd("add", 0));
691 cmd->init();
692 cmd->add_name("create");
693 cmd->add_name("make");
694 cset->add(cmd= new cl_timer_delete_cmd("delete", 0));
695 cmd->init();
696 cmd->add_name("remove");
697 cset->add(cmd= new cl_timer_get_cmd("get", 0));
698 cmd->init();
699 cset->add(cmd= new cl_timer_run_cmd("run", 0));
700 cmd->init();
701 cmd->add_name("start");
702 cset->add(cmd= new cl_timer_stop_cmd("stop", 0));
703 cmd->init();
704 cset->add(cmd= new cl_timer_value_cmd("set", 0));
705 cmd->init();
706 cmd->add_name("value");
707 }
708 if (!super_cmd) {
709 cmdset->add(cmd= new cl_super_cmd("timer", 0, cset));
710 cmd->init();
711 set_timer_help(cmd);
712 }
713
714 {
715 class cl_super_cmd *mem_create;
716 class cl_cmdset *mem_create_cset;
717 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("memory"));
718 if (super_cmd)
719 cset= super_cmd->get_subcommands();
720 else {
721 cset= new cl_cmdset();
722 cset->init();
723 }
724 /*
725 cset->add(cmd= new cl_memory_cmd("_no_parameters_", 0));
726 cmd->init();
727 */
728 mem_create= (class cl_super_cmd *)cset->get_cmd("create");
729 if (mem_create)
730 mem_create_cset= mem_create->get_subcommands();
731 else {
732 mem_create_cset= new cl_cmdset();
733 mem_create_cset->init();
734 }
735
736 mem_create_cset->add(cmd= new cl_memory_create_chip_cmd("chip", 0));
737 cmd->init();
738
739 mem_create_cset->add(cmd= new cl_memory_create_addressspace_cmd("addressspace", 0));
740 cmd->init();
741 cmd->add_name("addrspace");
742 cmd->add_name("aspace");
743 cmd->add_name("as");
744 cmd->add_name("addrs");
745 cmd->add_name("addr");
746
747 mem_create_cset->add(cmd= new cl_memory_create_addressdecoder_cmd("addressdecoder", 0));
748 cmd->init();
749 cmd->add_name("addrdecoder");
750 cmd->add_name("adecoder");
751 cmd->add_name("addressdec");
752 cmd->add_name("addrdec");
753 cmd->add_name("adec");
754 cmd->add_name("ad");
755
756 mem_create_cset->add(cmd= new cl_memory_create_banker_cmd("banker", 0));
757 cmd->init();
758 cmd->add_name("bankswitcher");
759 cmd->add_name("banksw");
760 cmd->add_name("bsw");
761 cmd->add_name("bs");
762
763 mem_create_cset->add(cmd= new cl_memory_create_bank_cmd("bank", 0));
764 cmd->init();
765
766 mem_create_cset->add(cmd= new cl_memory_create_bander_cmd("bander", 0));
767 cmd->init();
768 cmd->add_name("bitbander");
769 cmd->add_name("bitband");
770 cmd->add_name("band");
771 cmd->add_name("bb");
772
773 if (!mem_create)
774 cset->add(mem_create= new cl_super_cmd("create", 0, mem_create_cset));
775 mem_create->init();
776 mem_create->add_name("add");
777 set_memory_create_help(mem_create);
778
779 cset->add(cmd= new cl_info_memory_cmd("info", 0));
780 cmd->init();
781 cset->add(cmd= new cl_memory_cell_cmd("cell", 0));
782 cmd->init();
783 }
784 if (!super_cmd) {
785 cmdset->add(cmd= new cl_super_cmd("memory", 0, cset));
786 cmd->init();
787 set_memory_help(cmd);
788 }
789
790 cmdset->add(cmd= new cl_var_cmd("var", 0));
791 cmd->init();
792 cmd->add_name("variable");
793 }
794
795
796 /*
797 * Read/write simulated memory
798 */
799
800 t_mem
read_mem(char * id,t_addr addr)801 cl_uc::read_mem(char *id, t_addr addr)
802 {
803 class cl_address_space *m= address_space(id);
804
805 return(m?(m->read(addr)):0);
806 }
807
808 t_mem
get_mem(char * id,t_addr addr)809 cl_uc::get_mem(char *id, t_addr addr)
810 {
811 class cl_address_space *m= address_space(id);
812
813 return(m?(m->get(addr)):0);
814 }
815
816 void
write_mem(char * id,t_addr addr,t_mem val)817 cl_uc::write_mem(char *id, t_addr addr, t_mem val)
818 {
819 class cl_address_space *m= address_space(id);
820
821 if (m)
822 m->write(addr, val);
823 }
824
825 void
set_mem(char * id,t_addr addr,t_mem val)826 cl_uc::set_mem(char *id, t_addr addr, t_mem val)
827 {
828 class cl_address_space *m= address_space(id);
829
830 if(m)
831 m->set(addr, val);
832 }
833
834
835 /*
836 class cl_memory *
837 cl_uc::mem(enum mem_class type)
838 {
839 class cl_m *m;
840
841 if (mems->count < type)
842 m= (class cl_m *)(mems->at(MEM_DUMMY));
843 else
844 m= (class cl_m *)(mems->at(type));
845 return(m);
846 }
847 */
848
849 class cl_address_space *
address_space(const char * id)850 cl_uc::address_space(const char *id)
851 {
852 int i;
853
854 if (!id ||
855 !(*id))
856 return(0);
857 for (i= 0; i < address_spaces->count; i++)
858 {
859 class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
860 if (!m ||
861 !m->have_real_name())
862 continue;
863 if (m->is_inamed(id))
864 return(m);
865 }
866 return(0);
867 }
868
869 class cl_address_space *
address_space(class cl_memory_cell * cell)870 cl_uc::address_space(class cl_memory_cell *cell)
871 {
872 return(address_space(cell, (t_addr*)NULL));
873 }
874
875 class cl_address_space *
address_space(class cl_memory_cell * cell,t_addr * addr)876 cl_uc::address_space(class cl_memory_cell *cell, t_addr *addr)
877 {
878 int i;
879
880 for (i= 0; i < address_spaces->count; i++)
881 {
882 class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
883 if (!m)
884 continue;
885 if (m->is_owned(cell, addr))
886 return(m);
887 }
888 return(0);
889 }
890
891 class cl_memory *
memory(const char * id)892 cl_uc::memory(const char *id)
893 {
894 int i;
895
896 if (!id ||
897 !(*id))
898 return(0);
899 for (i= 0; i < address_spaces->count; i++)
900 {
901 class cl_base *b= address_spaces->object_at(i);
902 class cl_memory *m= dynamic_cast<cl_memory *>(b);
903 if (!m ||
904 !m->have_real_name())
905 continue;
906 if (m->is_inamed(id))
907 return(m);
908 }
909 for (i= 0; i < memchips->count; i++)
910 {
911 class cl_memory *m= (cl_memory *)(memchips->at(i));
912 if (!m ||
913 !m->have_real_name())
914 continue;
915 if (m->is_inamed(id))
916 return(m);
917 }
918 return(0);
919 }
920
921
922 static long
ReadInt(cl_f * f,bool * ok,int bytes)923 ReadInt(cl_f *f, bool *ok, int bytes)
924 {
925 char s2[3];
926 long l= 0;
927 int c;
928
929 *ok= false;
930 while (bytes)
931 {
932 if (f->eof())
933 return(0);
934 c= f->get_c();
935 if ((c < 0) ||
936 (c == 0) ||
937 (c > 0xff))
938 return 0;
939 s2[0]= c;
940 if (f->eof())
941 return(0);
942 c= f->get_c();
943 if ((c < 0) ||
944 (c == 0) ||
945 (c > 0xff))
946 return 0;
947 s2[1]= c;
948 s2[2]= '\0';
949 l= l*256 + strtol(s2, NULL, 16);
950 bytes--;
951 }
952 *ok= true;
953 return(l);
954 }
955
956
957 /*
958 * Reading intel hexa file into EROM
959 *____________________________________________________________________________
960 *
961 * If parameter is a NULL pointer, this function reads data from `cmd_in'
962 *
963 */
964
965 void
set_rom(t_addr addr,t_mem val)966 cl_uc::set_rom(t_addr addr, t_mem val)
967 {
968 //printf("rom[%06lx]=%02x\n", addr, val);
969 t_addr size= rom->get_size();
970 if (addr < size)
971 {
972 rom->download(addr, val);
973 return;
974 }
975 t_addr bank, caddr;
976 bank= addr / size;
977 caddr= addr % size;
978 //printf("getting decoder of %ld/%lx\n", bank, caddr);
979 class cl_banker *d= (class cl_banker *)(rom->get_decoder_of(caddr));
980 if (d)
981 {
982 if (!d->is_banker())
983 {
984 //printf("cell at %lx has no banker\n", caddr);
985 return;
986 }
987 //printf("setting %ld/rom[%lx]=%x\n", bank, caddr, val);
988 d->switch_to(bank, NULL);
989 rom->download(caddr, val);
990 d->activate(NULL);
991 }
992 else
993 ;//printf("no decoder at %lx\n", caddr);
994 }
995
996 long
read_hex_file(const char * nam)997 cl_uc::read_hex_file(const char *nam)
998 {
999 cl_f *f;
1000
1001 if (!nam)
1002 {
1003 fprintf(stderr, "cl_uc::read_hex_file File name not specified\n");
1004 return(-1);
1005 }
1006 else
1007 if ((f= /*fopen*/mk_io(nam, "r")) == NULL)
1008 {
1009 fprintf(stderr, "Can't open `%s': %s\n", nam, strerror(errno));
1010 return(-1);
1011 }
1012 long l= read_hex_file(f);
1013 delete f;
1014 return l;
1015 }
1016
1017 long
read_hex_file(cl_console_base * con)1018 cl_uc::read_hex_file(cl_console_base *con)
1019 {
1020 cl_f *f;
1021 if (con == NULL)
1022 return -1;
1023 f= con->get_fin();
1024 if (f == NULL)
1025 return -1;
1026 long l= read_hex_file(f);
1027 return l;
1028 }
1029
1030 long
read_hex_file(cl_f * f)1031 cl_uc::read_hex_file(cl_f *f)
1032 {
1033 int c;
1034 long written= 0, recnum= 0;
1035
1036 uint base= 0; // extended address, added to every adress
1037 uchar dnum; // data number
1038 uchar rtyp=0; // record type
1039 uint addr= 0; // address
1040 uchar rec[300]; // data record
1041 uchar sum ; // checksum
1042 uchar chk ; // check
1043 int i;
1044 bool ok, get_low= 1;
1045 uchar low= 0, high;
1046
1047 if (!rom)
1048 {
1049 sim->app->get_commander()->
1050 dd_printf("No ROM address space to read in.\n");
1051 return(-1);
1052 }
1053
1054 //memset(inst_map, '\0', sizeof(inst_map));
1055 ok= true;
1056 while (ok &&
1057 rtyp != 1)
1058 {
1059 while (((c= /*getc(f)*/f->get_c()) != ':') &&
1060 (/*c != EOF*/!f->eof())) /*printf("search_record=%c\n",c)*/;
1061 if (c != ':')
1062 {fprintf(stderr, ": not found\n");break;}
1063 recnum++;
1064 dnum= ReadInt(f, &ok, 1);//printf("%ld:dnum=%02x ",recnum,dnum);
1065 chk = dnum;
1066 addr= ReadInt(f, &ok, 2);//printf("%ld:addr=%04x ",recnum,addr);
1067 chk+= (addr & 0xff);
1068 chk+= ((addr >> 8) & 0xff);
1069 rtyp= ReadInt(f, &ok, 1);//printf("%ld:rtyp=%02x ",recnum,rtyp);
1070 chk+= rtyp;
1071 for (i= 0; ok && (i < dnum); i++)
1072 {
1073 rec[i]= ReadInt(f, &ok, 1);//printf("%02x",rec[i]);
1074 chk+= rec[i];
1075 }
1076 if (ok)
1077 {
1078 sum= ReadInt(f, &ok, 1);//printf(" %ld:sum=%02x\n",recnum,sum);
1079 if (ok)
1080 {
1081 if (((sum + chk) & 0xff) == 0)
1082 {
1083 if (rtyp == 0)
1084 {
1085 if (rom->width > 8)
1086 addr/= 2;
1087 for (i= 0; i < dnum; i++)
1088 {
1089 if (rom->width <= 8)
1090 {
1091 set_rom(base+addr, rec[i]);
1092 addr++;
1093 written++;
1094 }
1095 else if (rom->width <= 16)
1096 {
1097 if (get_low)
1098 {
1099 low= rec[i];
1100 get_low= 0;
1101 }
1102 else
1103 {
1104 high= rec[i];
1105 set_rom(base+addr, (high*256)+low);
1106 addr++;
1107 written++;
1108 get_low= 1;
1109 }
1110 }
1111 }
1112 }
1113 else if (rtyp == 4)
1114 {
1115 //printf("hex record type=4\n");
1116 if (dnum >= 2)
1117 {
1118 base= (rec[0]*256+rec[1]) << 16;
1119 //printf("hex base=%x\n", base);
1120 }
1121 }
1122 else
1123 if (rtyp != 1)
1124 /*application->debug*/fprintf(stderr, "Unknown record type %d(0x%x)\n",
1125 rtyp, rtyp);
1126 }
1127 else
1128 /*application->debug*/fprintf(stderr, "Checksum error (%x instead of %x) in "
1129 "record %ld.\n", chk, sum, recnum);
1130 }
1131 else
1132 /*application->debug*/fprintf(stderr, "Read error in record %ld.\n", recnum);
1133 }
1134 }
1135 if (rom->width > 8 &&
1136 !get_low)
1137 rom->set(addr, low);
1138
1139 analyze(0);
1140 return(written);
1141 }
1142
1143 long
read_omf_file(cl_f * f)1144 cl_uc::read_omf_file(cl_f *f)
1145 {
1146 long written= 0;
1147 class cl_omf_rec rec;
1148 while (rec.read(f))
1149 {
1150 if (rec.type == 0x06)
1151 {
1152 // content
1153 u16_t addr= rec.pick_word(1);
1154 int i= 3;
1155 while (i < rec.len)
1156 {
1157 set_rom(addr+i, rec.rec[i]);
1158 written++;
1159 i++;
1160 }
1161 }
1162 }
1163 return (written);
1164 }
1165
1166 long
read_cdb_file(cl_f * f)1167 cl_uc::read_cdb_file(cl_f *f)
1168 {
1169 class cl_cdb_recs *fns= new cl_cdb_recs();
1170 chars ln;
1171 char *lc;
1172 long cnt= 0;
1173 class cl_cdb_rec *r;
1174 class cl_var *v;
1175
1176 ln= f->get_s();
1177 while (!ln.empty())
1178 {
1179 //printf("CBD LN=%s\n",(char*)ln);
1180 lc= (char*)ln;
1181 if (lc[0] == 'F')
1182 {
1183 if (ln.len() > 5)
1184 {
1185 if ((lc[1] == ':') &&
1186 (lc[2] == 'G'))
1187 {
1188 ln.start_parse(4);
1189 chars n= ln.token("$");
1190 if ((r= fns->rec(n)) != NULL)
1191 {
1192 vars->add(v= new cl_var(n, rom, r->addr, ""));
1193 v->init();
1194 fns->del(n);
1195 cnt++;
1196 }
1197 else
1198 fns->add(new cl_cdb_rec(n));
1199 }
1200 }
1201 }
1202 else if (lc[0] == 'L')
1203 {
1204 if (ln.len() > 5)
1205 {
1206 if ((ln[1] == ':') &&
1207 (lc[2] == 'G'))
1208 {
1209 ln.start_parse(4);
1210 chars n= ln.token("$");
1211 chars t= ln.token(":");
1212 t= ln.token(" ");
1213 t_addr a= strtol((char*)t, 0, 16);
1214 if ((r= fns->rec(n)) != NULL)
1215 {
1216 fns->del(n);
1217 vars->add(v= new cl_var(n, rom, a, ""));
1218 v->init();
1219 cnt++;
1220 }
1221 else
1222 fns->add(new cl_cdb_rec(n, a));
1223 }
1224 }
1225 }
1226 ln= f->get_s();
1227 }
1228 fns->free_all();
1229 delete fns;
1230 return cnt;
1231 }
1232
1233 cl_f *
find_loadable_file(chars nam)1234 cl_uc::find_loadable_file(chars nam)
1235 {
1236 cl_f *f;
1237 bool o;
1238 chars c;
1239
1240 f= mk_io(nam, "r");
1241 o= (f->opened());
1242 if (o)
1243 return f;
1244
1245 c= chars("", "%s.ihx", (char*)nam);
1246 f->open(c, chars("r"));
1247 o= (f->opened());
1248 if (o)
1249 return f;
1250 c= chars("", "%s.hex", (char*)nam);
1251 f->open(c, chars("r"));
1252 o= (f->opened());
1253 if (o)
1254 return f;
1255 c= chars("", "%s.ihex", (char*)nam);
1256 f->open(c, chars("r"));
1257 o= (f->opened());
1258 if (o)
1259 return f;
1260
1261 c= chars("", "%s.omf", (char*)nam);
1262 f->open(c, chars("r"));
1263 o= (f->opened());
1264 if (o)
1265 return f;
1266
1267 delete f;
1268 return NULL;
1269 }
1270
1271 long
read_file(chars nam,class cl_console_base * con)1272 cl_uc::read_file(chars nam, class cl_console_base *con)
1273 {
1274 cl_f *f= find_loadable_file(nam);
1275 long l= 0;
1276
1277 if (!f)
1278 {
1279 if (con) con->dd_printf("no loadable file found\n");
1280 return 0;
1281 }
1282 /*if (con) con->dd_*/printf("Loading from %s\n", f->get_file_name());
1283 if (is_hex_file(f))
1284 {
1285 l= read_hex_file(f);
1286 printf("%ld words read from %s\n", l, f->get_fname());
1287 }
1288 else if (is_omf_file(f))
1289 {
1290 l= read_omf_file(f);
1291 printf("%ld words read from %s\n", l, f->get_fname());
1292 }
1293 else if (is_cdb_file(f))
1294 {
1295 l= read_cdb_file(f);
1296 printf("%ld symbols read from %s\n", l, f->get_fname());
1297 }
1298 if (strcmp(nam, f->get_fname()) != 0)
1299 {
1300 chars n= nam;
1301 n+= (char*)".cdb";
1302 cl_f *c= mk_io(n, "r");
1303 if (c->opened())
1304 {
1305 l= read_cdb_file(c);
1306 printf("%ld symbols read from %s\n", l, c->get_fname());
1307 }
1308 delete c;
1309 }
1310 delete f;
1311 return l;
1312 }
1313
1314
1315 /*
1316 * Handling instruction map
1317 *
1318 * `inst_at' is checking if the specified address is in instruction
1319 * map and `set_inst_at' marks the address in the map and
1320 * `del_inst_at' deletes the mark. `there_is_inst' cheks if there is
1321 * any mark in the map
1322 */
1323
1324 bool
inst_at(t_addr addr)1325 cl_uc::inst_at(t_addr addr)
1326 {
1327 if (!rom)
1328 return(0);
1329 return(rom->get_cell_flag(addr, CELL_INST));
1330 }
1331
1332 void
set_inst_at(t_addr addr)1333 cl_uc::set_inst_at(t_addr addr)
1334 {
1335 if (rom)
1336 rom->set_cell_flag(addr, true, CELL_INST);
1337 }
1338
1339 void
del_inst_at(t_addr addr)1340 cl_uc::del_inst_at(t_addr addr)
1341 {
1342 if (rom)
1343 rom->set_cell_flag(addr, false, CELL_INST);
1344 }
1345
1346 bool
there_is_inst(void)1347 cl_uc::there_is_inst(void)
1348 {
1349 if (!rom)
1350 return(0);
1351 bool got= false;
1352 t_addr addr;
1353 for (addr= 0; rom->valid_address(addr) && !got; addr++)
1354 got= rom->get_cell_flag(addr, CELL_INST);
1355 return(got);
1356 }
1357
1358
1359 /*
1360 * Manipulating HW elements of the CPU
1361 *****************************************************************************
1362 */
1363
1364 /* Register callback hw objects for mem read/write */
1365
1366 /*void
1367 cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
1368 {
1369 class cl_m *m;
1370 class cl_memloc *l;
1371
1372 if ((m= (class cl_m*)mems->at(type)))
1373 {
1374 if ((l= m->read_locs->get_loc(addr)) == 0)
1375 {
1376 l= new cl_memloc(addr);
1377 l->init();
1378 m->read_locs->add(l);
1379 }
1380 l->hws->add(hw);
1381 }
1382 else
1383 printf("cl_uc::register_hw_read TROUBLE\n");
1384 }*/
1385
1386 /*void
1387 cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
1388 {
1389 }*/
1390
1391 void
add_hw(class cl_hw * hw)1392 cl_uc::add_hw(class cl_hw *hw)
1393 {
1394 int i;
1395 for (i= 0; i < hws->count; i++)
1396 {
1397 class cl_hw *h= (class cl_hw *)(hws->at(i));
1398 h->new_hw_adding(hw);
1399 }
1400 hws->add(hw);
1401 for (i= 0; i < hws->count; i++)
1402 {
1403 class cl_hw *h= (class cl_hw *)(hws->at(i));
1404 if (h != hw)
1405 h->new_hw_added(hw);
1406 }
1407 }
1408
1409 int
nuof_hws(void)1410 cl_uc::nuof_hws(void)
1411 {
1412 return hws->count;
1413 }
1414
1415 /* Looking for a specific HW element */
1416
1417 class cl_hw *
get_hw(int idx)1418 cl_uc::get_hw(int idx)
1419 {
1420 if (idx >= hws->count)
1421 return NULL;
1422 return (class cl_hw *)(hws->at(idx));
1423 }
1424
1425 class cl_hw *
get_hw(enum hw_cath cath,int * idx)1426 cl_uc::get_hw(enum hw_cath cath, int *idx)
1427 {
1428 class cl_hw *hw= 0;
1429 int i= 0;
1430
1431 if (idx)
1432 i= *idx;
1433 for (; i < hws->count; i++)
1434 {
1435 hw= (class cl_hw *)(hws->at(i));
1436 if (hw->cathegory == cath)
1437 break;
1438 }
1439 if (i >= hws->count)
1440 return(0);
1441 if (idx)
1442 *idx= i;
1443 return(hw);
1444 }
1445
1446 class cl_hw *
get_hw(char * id_string,int * idx)1447 cl_uc::get_hw(char *id_string, int *idx)
1448 {
1449 class cl_hw *hw= 0;
1450 int i= 0;
1451
1452 if (idx)
1453 i= *idx;
1454 for (; i < hws->count; i++)
1455 {
1456 hw= (class cl_hw *)(hws->at(i));
1457 if (strstr(hw->id_string, id_string) == hw->id_string)
1458 break;
1459 }
1460 if (i >= hws->count)
1461 return(0);
1462 if (idx)
1463 *idx= i;
1464 return(hw);
1465 }
1466
1467 class cl_hw *
get_hw(enum hw_cath cath,int hwid,int * idx)1468 cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
1469 {
1470 class cl_hw *hw;
1471 int i= 0;
1472
1473 if (idx)
1474 i= *idx;
1475 hw= get_hw(cath, &i);
1476 while (hw &&
1477 hw->id != hwid)
1478 {
1479 i++;
1480 hw= get_hw(cath, &i);
1481 }
1482 if (hw &&
1483 idx)
1484 *idx= i;
1485 return(hw);
1486 }
1487
1488 class cl_hw *
get_hw(char * id_string,int hwid,int * idx)1489 cl_uc::get_hw(char *id_string, int hwid, int *idx)
1490 {
1491 class cl_hw *hw;
1492 int i= 0;
1493
1494 if (idx)
1495 i= *idx;
1496 hw= get_hw(id_string, &i);
1497 while (hw &&
1498 hw->id != hwid)
1499 {
1500 i++;
1501 hw= get_hw(id_string, &i);
1502 }
1503 if (hw &&
1504 idx)
1505 *idx= i;
1506 return(hw);
1507 }
1508
1509 int
get_max_hw_id(enum hw_cath cath)1510 cl_uc::get_max_hw_id(enum hw_cath cath)
1511 {
1512 class cl_hw *hw;
1513 int i, max= -1;
1514
1515 for (i= 0; i < hws->count; i++)
1516 {
1517 hw= (class cl_hw *)(hws->at(i));
1518 if (hw->id > max)
1519 max= hw->id;
1520 }
1521 return max;
1522 }
1523
1524 /*
1525 * Help of the command interpreter
1526 */
1527
1528 struct dis_entry *
dis_tbl(void)1529 cl_uc::dis_tbl(void)
1530 {
1531 static struct dis_entry empty= { 0, 0, 0, 0, NULL };
1532 return(&empty);
1533 }
1534
1535 char *
disass(t_addr addr,const char * sep)1536 cl_uc::disass(t_addr addr, const char *sep)
1537 {
1538 char *buf;
1539
1540 buf= (char*)malloc(100);
1541 strcpy(buf, "uc::disass() unimplemented\n");
1542 return(buf);
1543 }
1544
1545 void
print_disass(t_addr addr,class cl_console_base * con)1546 cl_uc::print_disass(t_addr addr, class cl_console_base *con)
1547 {
1548 char *dis;
1549 class cl_brk *b;
1550 int i, l;
1551
1552 if (!rom)
1553 return;
1554
1555 t_mem code= rom->get(addr);
1556 b= fbrk_at(addr);
1557 dis= disass(addr, NULL);
1558 if (b)
1559 con->dd_cprintf("answer", "%c", (b->perm == brkFIX)?'F':'D');
1560 else
1561 con->dd_printf(" ");
1562 con->dd_cprintf("answer", "%c ", inst_at(addr)?' ':'?');
1563 con->dd_cprintf("dump_address", rom->addr_format, addr); con->dd_printf(" ");
1564 con->dd_cprintf("dump_number", rom->data_format, code);
1565 l= inst_length(addr);
1566 for (i= 1; i < l; i++)
1567 {
1568 con->dd_printf(" ");
1569 con->dd_cprintf("dump_number", rom->data_format, rom->get(addr+i));
1570 }
1571 int li= longest_inst();
1572 while (i < li)
1573 {
1574 int j;
1575 j= rom->width/4 + ((rom->width%4)?1:0) + 1;
1576 while (j)
1577 con->dd_printf(" "), j--;
1578 i++;
1579 }
1580 con->dd_cprintf("dump_char", " %s\n", dis);
1581 free((char *)dis);
1582 }
1583
1584 void
print_regs(class cl_console_base * con)1585 cl_uc::print_regs(class cl_console_base *con)
1586 {
1587 con->dd_printf("No registers\n");
1588 }
1589
1590 int
inst_length(t_addr addr)1591 cl_uc::inst_length(t_addr addr)
1592 {
1593 struct dis_entry *tabl= dis_tbl();
1594 int i;
1595 t_mem code;
1596
1597 if (!rom)
1598 return(0);
1599
1600 code = rom->get(addr);
1601 for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++) ;
1602 return(tabl[i].mnemonic?tabl[i].length:1);
1603 }
1604
1605 int
inst_branch(t_addr addr)1606 cl_uc::inst_branch(t_addr addr)
1607 {
1608 struct dis_entry *tabl= dis_tbl();
1609 int i;
1610 t_mem code;
1611
1612 if (!rom)
1613 return(0);
1614
1615 code = rom->get(addr);
1616 for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
1617 ;
1618 return tabl[i].branch;
1619 }
1620
1621 bool
is_call(t_addr addr)1622 cl_uc::is_call(t_addr addr)
1623 {
1624 struct dis_entry *tabl= dis_tbl();
1625 int i;
1626 t_mem code;
1627
1628 if (!rom)
1629 return(0);
1630
1631 code = rom->get(addr);
1632 for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
1633 ;
1634 return tabl[i].is_call;
1635 }
1636
1637 int
longest_inst(void)1638 cl_uc::longest_inst(void)
1639 {
1640 struct dis_entry *de= dis_tbl();
1641 int max= 0;
1642
1643 while (de &&
1644 de->mnemonic)
1645 {
1646 if (de->length > max)
1647 max= de->length;
1648 de++;
1649 }
1650 return(max);
1651 }
1652
1653 bool
addr_name(t_addr addr,class cl_address_space * as,char * buf)1654 cl_uc::addr_name(t_addr addr, class cl_address_space *as, char *buf)
1655 {
1656 t_index i;
1657
1658 for (i= 0; i < vars->count; i++)
1659 {
1660 class cl_var *v= (cl_var *)(vars->at(i));
1661 if ((v->as == as) &&
1662 (v->addr == addr))
1663 {
1664 strcpy(buf, v->get_name());
1665 return true;
1666 }
1667 }
1668 unsigned int a= addr;
1669 sprintf(buf, "%02x", a);
1670 return false;
1671 }
1672
1673 bool
addr_name(t_addr addr,class cl_address_space * as,int bitnr,char * buf)1674 cl_uc::addr_name(t_addr addr, class cl_address_space *as, int bitnr, char *buf)
1675 {
1676 t_index i;
1677
1678 for (i= 0; i < vars->count; i++)
1679 {
1680 class cl_var *v= (cl_var *)(vars->at(i));
1681 if ((v->as == as) &&
1682 (v->addr == addr) &&
1683 (v->bitnr == bitnr))
1684 {
1685 strcpy(buf, v->get_name());
1686 return true;
1687 }
1688 }
1689 unsigned int a= addr;
1690 sprintf(buf, "%02x.%d", a, bitnr);
1691 return false;
1692 }
1693
1694 bool
symbol2address(char * sym,class cl_address_space ** as,t_addr * addr)1695 cl_uc::symbol2address(char *sym,
1696 class cl_address_space **as,
1697 t_addr *addr)
1698 {
1699 class cl_var *v;
1700 t_index i;
1701
1702 if (!sym ||
1703 !*sym)
1704 return false;
1705 if (vars->search(sym, i))
1706 {
1707 v= (class cl_var *)(vars->at(i));
1708 if (v->bitnr >= 0)
1709 return false;
1710 if (as)
1711 *as= v->as;
1712 if (addr)
1713 *addr= v->addr;
1714 return true;
1715 }
1716 return false;
1717 }
1718
1719 char *
symbolic_bit_name(t_addr bit_address,class cl_memory * mem,t_addr mem_addr,t_mem bit_mask)1720 cl_uc::symbolic_bit_name(t_addr bit_address,
1721 class cl_memory *mem,
1722 t_addr mem_addr,
1723 t_mem bit_mask)
1724 {
1725 //char *sym_name= 0;
1726 int i;
1727 chars c= chars("", mem?(mem->addr_format):"0x%06lx", (unsigned long)mem_addr);
1728 /*if (!sym_name)
1729 {
1730 sym_name= (char *)malloc(16);
1731 sprintf(sym_name, mem?(mem->addr_format):"0x%06lx", (unsigned long)mem_addr);
1732 }*/
1733 /*sym_name= (char *)realloc(sym_name, strlen(sym_name)+2);
1734 strcat(sym_name, ".");*/
1735 c+= cchars(".");
1736 i= 0;
1737 while (bit_mask > 1)
1738 {
1739 bit_mask>>=1;
1740 i++;
1741 }
1742 //char bitnumstr[10];
1743 /*sprintf(bitnumstr, "%1d", i);
1744 strcat(sym_name, bitnumstr);*/
1745 c.append("%d", i);
1746 return(/*sym_name*/strdup((char*)c));
1747 }
1748
1749
1750 /*
1751 * Searching for a name in the specified table
1752 */
1753
1754 struct name_entry *
get_name_entry(struct name_entry tabl[],char * name)1755 cl_uc::get_name_entry(struct name_entry tabl[], char *name)
1756 {
1757 int i= 0;
1758 char *p;
1759
1760 if (!tabl ||
1761 !name ||
1762 !(*name))
1763 return(0);
1764 for (p= name; *p; *p= toupper(*p), p++);
1765 while (tabl[i].name &&
1766 (!(tabl[i].cpu_type & type->type) ||
1767 (strcmp(tabl[i].name, name) != 0)))
1768 {
1769 //printf("tabl[%d].name=%s <-> %s\n",i,tabl[i].name,name);
1770 i++;
1771 }
1772 if (tabl[i].name != NULL)
1773 return(&tabl[i]);
1774 else
1775 return(0);
1776 }
1777
1778 chars
cell_name(class cl_memory_cell * cell)1779 cl_uc::cell_name(class cl_memory_cell *cell)
1780 {
1781 if (cell == NULL)
1782 return chars("");
1783 if (cell->get_flag(CELL_VAR))
1784 {
1785 int i;
1786 for (i= 0; i < vars->count; i++)
1787 {
1788 class cl_var *v= (cl_var*)(vars->at(i));
1789 if (v->get_cell() &&
1790 (cell == v->get_cell()))
1791 return chars(v->get_name());
1792 }
1793 }
1794 class cl_address_space *as;
1795 t_addr a;
1796 as= address_space(cell, &a);
1797 if (as == NULL)
1798 return chars("");
1799 return chars("", "%s_%06x", as->get_name(), a);
1800 }
1801
1802 class cl_var *
var(char * nam)1803 cl_uc::var(char *nam)
1804 {
1805 if (!vars)
1806 return NULL;
1807 t_index i;
1808 if (!vars->search(nam, i))
1809 return NULL;
1810 class cl_var *v= (cl_var*)(vars->at(i));
1811 return v;
1812 }
1813
1814
1815 /*
1816 * Messages to broadcast
1817 */
1818
1819 bool
handle_event(class cl_event & event)1820 cl_uc::handle_event(class cl_event &event)
1821 {
1822 switch (event.what)
1823 {
1824 case ev_address_space_added:
1825 {
1826 try {
1827 class cl_event_address_space_added &e=
1828 dynamic_cast<class cl_event_address_space_added &>(event);
1829 address_space_added(e.as);
1830 e.handle();
1831 }
1832 catch (...)
1833 { break; }
1834 break;
1835 }
1836 default:
1837 return(pass_event_down(event));
1838 break;
1839 }
1840 return(false);
1841 }
1842
1843 /*
1844 void
1845 cl_uc::mem_cell_changed(class cl_address_space *mem, t_addr addr)
1846 {
1847 if (hws)
1848 hws->mem_cell_changed(mem, addr);
1849 else
1850 printf("JAJ uc\n");//FIXME
1851 if (mems &&
1852 mems->count)
1853 {
1854 int i;
1855 for (i= 0; i < mems->count; i++)
1856 {
1857 }
1858 }
1859 }
1860 */
1861
1862 void
address_space_added(class cl_address_space * as)1863 cl_uc::address_space_added(class cl_address_space *as)
1864 {
1865 /*
1866 if (hws)
1867 hws->address_space_added(as);
1868 else
1869 printf("JAJ uc\n");//FIXME
1870 */
1871 }
1872
1873
1874 /*
1875 * Error handling
1876 */
1877
1878 void
error(class cl_error * error)1879 cl_uc::error(class cl_error *error)
1880 {
1881 //printf("error adding: %s...\n", error->get_class()->get_name());
1882 errors->add(error);
1883 if ((error->inst= inst_exec))
1884 error->PC= instPC;
1885 }
1886
1887 void
check_errors(void)1888 cl_uc::check_errors(void)
1889 {
1890 int i;
1891 class cl_commander_base *c= sim->app->get_commander();
1892 bool must_stop= false;
1893
1894 if (c)
1895 {
1896 //printf("error list: %d items\n", errors->count);
1897 for (i= 0; i < errors->count; i++)
1898 {
1899 class cl_error *error= (class cl_error *)(errors->at(i));
1900 if (!error->is_on())
1901 continue;
1902 error->print(c);
1903 must_stop= must_stop || (error->get_type() & err_stop);
1904 if (error->inst)
1905 {
1906 class cl_console_base *con;
1907 con= c->actual_console;
1908 if (!con)
1909 con= c->frozen_console;
1910 if (con)
1911 {
1912 con->dd_printf("Erronouse instruction: ");
1913 print_disass(error->PC, con);
1914 }
1915 }
1916 }
1917 errors->free_all();
1918 }
1919 else
1920 fprintf(stderr, "no actual console, %d errors\n", errors->count);
1921 if (must_stop)
1922 sim->stop(resERROR);
1923 }
1924
1925
1926 /*
1927 * Converting bit address into real memory
1928 */
1929
1930 class cl_address_space *
bit2mem(t_addr bitaddr,t_addr * memaddr,t_mem * bitmask)1931 cl_uc::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
1932 {
1933 if (memaddr)
1934 *memaddr= bitaddr;
1935 if (bitmask)
1936 *bitmask= 1 << (bitaddr & 0x7);
1937 return(0); // abstract...
1938 }
1939
1940
1941 /*
1942 * Execution
1943 */
1944
1945 int
tick_hw(int cycles)1946 cl_uc::tick_hw(int cycles)
1947 {
1948 class cl_hw *hw;
1949 int i;//, cpc= clock_per_cycle();
1950
1951 // tick hws
1952 for (i= 0; i < hws->count; i++)
1953 {
1954 hw= (class cl_hw *)(hws->at(i));
1955 if ((hw->flags & HWF_INSIDE) &&
1956 (hw->on))
1957 hw->tick(cycles);
1958 }
1959 do_extra_hw(cycles);
1960 return(0);
1961 }
1962
1963 void
do_extra_hw(int cycles)1964 cl_uc::do_extra_hw(int cycles)
1965 {}
1966
1967 int
tick(int cycles)1968 cl_uc::tick(int cycles)
1969 {
1970 //class cl_hw *hw;
1971 int i, cpc= clock_per_cycle();
1972
1973 // increase time
1974 ticks->tick(cycles * cpc);
1975 class it_level *il= (class it_level *)(it_levels->top());
1976 if (il->level >= 0)
1977 isr_ticks->tick(cycles * cpc);
1978 if (state == stIDLE)
1979 idle_ticks->tick(cycles * cpc);
1980 for (i= 0; i < counters->count; i++)
1981 {
1982 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
1983 if (t)
1984 {
1985 if ((t->options&TICK_INISR) ||
1986 il->level < 0)
1987 t->tick(cycles * cpc);
1988 }
1989 }
1990
1991 // tick for hardwares
1992 inst_ticks+= cycles;
1993 return(0);
1994 }
1995
1996 class cl_ticker *
get_counter(int nr)1997 cl_uc::get_counter(int nr)
1998 {
1999 if (nr >= counters->count)
2000 return(0);
2001 return((class cl_ticker *)(counters->at(nr)));
2002 }
2003
2004 class cl_ticker *
get_counter(const char * nam)2005 cl_uc::get_counter(const char *nam)
2006 {
2007 int i;
2008
2009 if (!nam)
2010 return(0);
2011 for (i= 0; i < counters->count; i++)
2012 {
2013 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2014 if (t &&
2015 t->get_name() &&
2016 strcmp(t->get_name(), nam) == 0)
2017 return(t);
2018 }
2019 return(0);
2020 }
2021
2022 void
add_counter(class cl_ticker * ticker,int nr)2023 cl_uc::add_counter(class cl_ticker *ticker, int nr)
2024 {
2025 while (counters->count <= nr)
2026 counters->add(0);
2027 counters->put_at(nr, ticker);
2028 }
2029
2030 void
add_counter(class cl_ticker * ticker,const char *)2031 cl_uc::add_counter(class cl_ticker *ticker, const char */*nam*/)
2032 {
2033 int i;
2034
2035 if (counters->count < 1)
2036 counters->add(0);
2037 for (i= 1; i < counters->count; i++)
2038 {
2039 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2040 if (!t)
2041 {
2042 counters->put_at(i, ticker);
2043 return;
2044 }
2045 }
2046 counters->add(ticker);
2047 }
2048
2049 void
del_counter(int nr)2050 cl_uc::del_counter(int nr)
2051 {
2052 class cl_ticker *t;
2053
2054 if (nr >= counters->count)
2055 return;
2056 if ((t= (class cl_ticker *)(counters->at(0))) != 0)
2057 delete t;
2058 counters->put_at(nr, 0);
2059 }
2060
2061 void
del_counter(const char * nam)2062 cl_uc::del_counter(const char *nam)
2063 {
2064 int i;
2065
2066 if (!nam)
2067 return;
2068 for (i= 0; i < counters->count; i++)
2069 {
2070 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2071 if (t &&
2072 t->get_name() &&
2073 strcmp(t->get_name(), nam) == 0)
2074 {
2075 delete t;
2076 counters->put_at(i, 0);
2077 return;
2078 }
2079 }
2080 }
2081
2082 /*
2083 * Fetch without checking for breakpoint hit
2084 */
2085
2086 t_mem
fetch(void)2087 cl_uc::fetch(void)
2088 {
2089 ulong code;
2090
2091 if (!rom)
2092 return(0);
2093
2094 code= rom->read(PC);
2095 PC= rom->inc_address(PC);
2096 vc.fetch++;
2097 return(code);
2098 }
2099
2100 /*
2101 * Fetch but checking for breakpoint hit first, returns TRUE if
2102 * a breakpoint is hit
2103 */
2104
2105 bool
fetch(t_mem * code)2106 cl_uc::fetch(t_mem *code)
2107 {
2108 class cl_brk *brk;
2109 int idx;
2110
2111 if (!code)
2112 return(0);
2113 if ((sim->state & SIM_GO) &&
2114 rom &&
2115 (sim->steps_done > 0))
2116 {
2117 if (rom->get_cell_flag(PC, CELL_FETCH_BRK))
2118 if ((brk= fbrk->get_bp(PC, &idx)))
2119 if (brk->do_hit())
2120 {
2121 if (brk->perm == brkDYNAMIC)
2122 fbrk->del_bp(PC);
2123 return(1);
2124 }
2125 }
2126 *code= fetch();
2127 return(0);
2128 }
2129
2130 int
do_inst(int step)2131 cl_uc::do_inst(int step)
2132 {
2133 t_addr PCsave;
2134 int res= resGO;
2135
2136 if (step < 0)
2137 step= 1;
2138 while (step-- &&
2139 res == resGO)
2140 {
2141 pre_inst();
2142 PCsave = PC;
2143 res= exec_inst();
2144
2145 if (res == resINV_INST)
2146 /* backup to start of instruction */
2147 PC = PCsave;
2148
2149 post_inst();
2150
2151 if ((res == resGO) &&
2152 irq)
2153 {
2154 //printf("DO INTERRUPT PC=%lx\n", PC);
2155 int r= do_interrupt();
2156 if (r != resGO)
2157 res= r;
2158 }
2159
2160 if (stop_at_time &&
2161 stop_at_time->reached())
2162 {
2163 delete stop_at_time;
2164 stop_at_time= NULL;
2165 res= resBREAKPOINT;
2166 }
2167 }
2168 if (res != resGO)
2169 sim->stop(res);
2170 return(res);
2171 }
2172
2173 void
pre_inst(void)2174 cl_uc::pre_inst(void)
2175 {
2176 inst_exec= true;
2177 inst_ticks= 0;
2178 events->disconn_all();
2179 vc.inst++;
2180 }
2181
2182 int
exec_inst(void)2183 cl_uc::exec_inst(void)
2184 {
2185 instPC= PC;
2186 return(resGO);
2187 }
2188
2189 int
exec_inst_tab(instruction_wrapper_fn itab[])2190 cl_uc::exec_inst_tab(instruction_wrapper_fn itab[])
2191 {
2192 t_mem c;
2193 int res= resGO;
2194 instPC= PC;
2195 if (fetch(&c))
2196 return resBREAKPOINT;
2197 if (itab[c] == NULL)
2198 {
2199 PC= instPC;
2200 return resNOT_DONE;
2201 }
2202 res= itab[c](this, c);
2203 if (res == resNOT_DONE)
2204 {
2205 PC= instPC;
2206 return res;
2207 }
2208 tick(1);
2209 return res;
2210 }
2211
2212
2213 void
post_inst(void)2214 cl_uc::post_inst(void)
2215 {
2216 tick_hw(inst_ticks);
2217 if (errors->count)
2218 check_errors();
2219 if (events->count)
2220 check_events();
2221 inst_exec= false;
2222 }
2223
2224
2225 /*
2226 * Interrupt processing
2227 */
2228
2229 int
do_interrupt(void)2230 cl_uc::do_interrupt(void)
2231 {
2232 int i;
2233 // NMI?
2234
2235 // Maskable interrupts
2236 if (!it_enabled())
2237 {
2238 //printf("do_interrupt skip (it disabled)\n");
2239 return resGO;
2240 }
2241 class it_level *il= (class it_level *)(it_levels->top()), *IL= 0;
2242 irq= false;
2243 //printf("Checking IRQs...\n");
2244 for (i= 0; i < it_sources->count; i++)
2245 {
2246 class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
2247 if (is->is_active() &&
2248 is->enabled() &&
2249 is->pending())
2250 {
2251 int pr= priority_of(is->nuof);
2252 int ap;
2253 irq= true;
2254 if (il &&
2255 il->level >= 0)
2256 ap= il->level;
2257 else
2258 ap= priority_main();
2259 if (ap >= pr)
2260 continue;
2261 is->clear();
2262 sim->app->get_commander()->
2263 debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
2264 get_rtime(), ticks->ticks, object_name(is), PC);
2265 IL= new it_level(pr, is->addr, PC, is);
2266 return(accept_it(IL));
2267 }
2268 }
2269 return resGO;
2270 }
2271
2272 int
accept_it(class it_level * il)2273 cl_uc::accept_it(class it_level *il)
2274 {
2275 it_levels->push(il);
2276 return resGO;
2277 }
2278
2279
2280 /*
2281 * Time related functions
2282 */
2283
2284 double
get_rtime(void)2285 cl_uc::get_rtime(void)
2286 {
2287 /* double d;
2288
2289 d= (double)ticks/xtal;
2290 return(d);*/
2291 return(ticks->get_rtime(xtal));
2292 }
2293
2294 unsigned long
clocks_of_time(double t)2295 cl_uc::clocks_of_time(double t)
2296 {
2297 return (unsigned long)(t * xtal);
2298 }
2299
2300 int
clock_per_cycle(void)2301 cl_uc::clock_per_cycle(void)
2302 {
2303 return(1);
2304 }
2305
2306 void
touch(void)2307 cl_uc::touch(void)
2308 {
2309 class cl_hw *hw;
2310 int i;
2311 for (i= 0; i < hws->count; i++)
2312 {
2313 hw= (class cl_hw *)(hws->at(i));
2314 hw->touch();
2315 }
2316 }
2317
2318
2319 /*
2320 * Stack tracking system
2321 */
2322
2323 void
stack_write(class cl_stack_op * op)2324 cl_uc::stack_write(class cl_stack_op *op)
2325 {
2326 delete op;
2327 return ;
2328 if (op->get_op() & stack_read_operation)
2329 {
2330 class cl_error_stack_tracker_wrong_handle *e= new
2331 cl_error_stack_tracker_wrong_handle(false);
2332 e->init();
2333 error(e);
2334 return;
2335 }
2336 stack_ops->push(op);
2337 }
2338
2339 void
stack_read(class cl_stack_op * op)2340 cl_uc::stack_read(class cl_stack_op *op)
2341 {
2342 delete op;
2343 return ;
2344 class cl_stack_op *top= (class cl_stack_op *)(stack_ops->top());
2345
2346 if (op->get_op() & stack_write_operation)
2347 {
2348 class cl_error_stack_tracker_wrong_handle *e= new
2349 cl_error_stack_tracker_wrong_handle(true);
2350 e->init();
2351 error(e);
2352 return;
2353 }
2354 if (!top)
2355 {
2356 class cl_error *e= new cl_error_stack_tracker_empty(op);
2357 e->init();
2358 error(e);
2359 return;
2360 }
2361
2362 if (top)
2363 {
2364 if (!top->match(op))
2365 {
2366 class cl_error *e= new cl_error_stack_tracker_unmatch(top, op);
2367 e->init();
2368 error(e);
2369 }
2370 int top_size= top->data_size(), op_size= op->data_size();
2371 if (top_size != op_size)
2372 {
2373 application->debug("0x%06x %d bytes to read out of stack "
2374 "but %d was pushed in last operation\n",
2375 (int)op->get_pc(), op_size, top_size);
2376 }
2377 }
2378
2379 int removed= 0;
2380 while (top &&
2381 top->can_removed(op))
2382 {
2383 top= (class cl_stack_op *)stack_ops->pop();
2384 delete top;
2385 top= (class cl_stack_op *)stack_ops->top();
2386 removed++;
2387 }
2388 if (removed != 1)
2389 {
2390 application->debug("0x%06x %d ops removed from stack-tracker "
2391 "when %s happened, top pc=0x%06x "
2392 "top before=0x%06x op after=0x%06x\n",
2393 (int)op->get_pc(), removed, op->get_op_name(),
2394 top?((int)top->get_pc()):0,
2395 top?((int)top->get_before()):0,
2396 (int)op->get_after());
2397 }
2398
2399 if (top)
2400 {
2401 int ta= top->get_after(), oa= op->get_after();
2402 if (ta != oa)
2403 {
2404 application->debug("0x%06x stack still inconsistent after %s, "
2405 "%d byte(s) should be read out; top after"
2406 "=0x%06x op after=0x%06x\n",
2407 (int)op->get_pc(),
2408 op->get_op_name(),
2409 abs(ta-oa),
2410 ta, oa);
2411 class cl_error *e=
2412 new cl_error_stack_tracker_inconsistent(op, abs(ta-oa));
2413 e->init();
2414 error(e);
2415 }
2416 }
2417
2418 delete op;
2419 }
2420
2421 /*
2422 * Breakpoint handling
2423 */
2424
2425 class cl_fetch_brk *
fbrk_at(t_addr addr)2426 cl_uc::fbrk_at(t_addr addr)
2427 {
2428 int idx;
2429
2430 return((class cl_fetch_brk *)(fbrk->get_bp(addr, &idx)));
2431 }
2432
2433 class cl_ev_brk *
ebrk_at(t_addr addr,char * id)2434 cl_uc::ebrk_at(t_addr addr, char *id)
2435 {
2436 int i;
2437 class cl_ev_brk *eb;
2438
2439 for (i= 0; i < ebrk->count; i++)
2440 {
2441 eb= (class cl_ev_brk *)(ebrk->at(i));
2442 if (eb->addr == addr &&
2443 !strcmp(eb->id, id))
2444 return(eb);
2445 }
2446 return(0);
2447 }
2448
2449 /*void
2450 cl_uc::rm_fbrk(long addr)
2451 {
2452 fbrk->del_bp(addr);
2453 }*/
2454
2455 /* Get a breakpoint specified by its number */
2456
2457 class cl_brk *
brk_by_nr(int nr)2458 cl_uc::brk_by_nr(int nr)
2459 {
2460 class cl_brk *bp;
2461
2462 if ((bp= fbrk->get_bp(nr)))
2463 return(bp);
2464 if ((bp= ebrk->get_bp(nr)))
2465 return(bp);
2466 return(0);
2467 }
2468
2469 /* Get a breakpoint from the specified collection by its number */
2470
2471 class cl_brk *
brk_by_nr(class brk_coll * bpcoll,int nr)2472 cl_uc::brk_by_nr(class brk_coll *bpcoll, int nr)
2473 {
2474 class cl_brk *bp;
2475
2476 if ((bp= bpcoll->get_bp(nr)))
2477 return(bp);
2478 return(0);
2479 }
2480
2481 /* Remove an event breakpoint specified by its address and id */
2482
2483 void
rm_ebrk(t_addr addr,char * id)2484 cl_uc::rm_ebrk(t_addr addr, char *id)
2485 {
2486 int i;
2487 class cl_ev_brk *eb;
2488
2489 for (i= 0; i < ebrk->count; i++)
2490 {
2491 eb= (class cl_ev_brk *)(ebrk->at(i));
2492 if (eb->addr == addr &&
2493 !strcmp(eb->id, id))
2494 ebrk->del_bp(i, 0);
2495 }
2496 }
2497
2498 /* Remove a breakpoint specified by its number */
2499
2500 bool
rm_brk(int nr)2501 cl_uc::rm_brk(int nr)
2502 {
2503 class cl_brk *bp;
2504
2505 if ((bp= brk_by_nr(fbrk, nr)))
2506 {
2507 fbrk->del_bp(bp->addr);
2508 return(true);
2509 }
2510 else if ((bp= brk_by_nr(ebrk, nr)))
2511 {
2512 ebrk->del_bp(ebrk->index_of(bp), 0);
2513 return(true);
2514 }
2515 return(false);
2516 }
2517
2518 void
put_breaks(void)2519 cl_uc::put_breaks(void)
2520 {}
2521
2522 /* Remove all fetch and event breakpoints */
2523
2524 void
remove_all_breaks(void)2525 cl_uc::remove_all_breaks(void)
2526 {
2527 while (fbrk->count)
2528 {
2529 class cl_brk *brk= (class cl_brk *)(fbrk->at(0));
2530 fbrk->del_bp(brk->addr);
2531 }
2532 while (ebrk->count)
2533 ebrk->del_bp(ebrk->count-1, 0);
2534 }
2535
2536 int
make_new_brknr(void)2537 cl_uc::make_new_brknr(void)
2538 {
2539 if (brk_counter == 0)
2540 return(brk_counter= 1);
2541 if (fbrk->count == 0 &&
2542 ebrk->count == 0)
2543 return(brk_counter= 1);
2544 return(++brk_counter);
2545 }
2546
2547 class cl_ev_brk *
mk_ebrk(enum brk_perm perm,class cl_address_space * mem,char op,t_addr addr,int hit)2548 cl_uc::mk_ebrk(enum brk_perm perm, class cl_address_space *mem,
2549 char op, t_addr addr, int hit)
2550 {
2551 class cl_ev_brk *b;
2552 op= toupper(op);
2553
2554 b= new cl_ev_brk(mem, make_new_brknr(), addr, perm, hit, op);
2555 b->init();
2556 return(b);
2557 }
2558
2559 void
check_events(void)2560 cl_uc::check_events(void)
2561 {
2562 int i;
2563 //sim->stop(resEVENTBREAK);
2564 for (i= 0; i < events->count; i++)
2565 {
2566 class cl_ev_brk *brk=
2567 dynamic_cast<class cl_ev_brk *>(events->object_at(i));
2568 sim->stop(resEVENTBREAK, brk);
2569 }
2570 }
2571
2572 void
stop_when(class cl_time_measurer * t)2573 cl_uc::stop_when(class cl_time_measurer *t)
2574 {
2575 if (stop_at_time != NULL)
2576 delete stop_at_time;
2577 stop_at_time= t;
2578 }
2579
2580
2581 /*
2582 * Errors
2583 *----------------------------------------------------------------------------
2584 */
2585
cl_error_unknown_code(class cl_uc * the_uc)2586 cl_error_unknown_code::cl_error_unknown_code(class cl_uc *the_uc)
2587 {
2588 uc= the_uc;
2589 classification= uc_error_registry.find("unknown_code");
2590 }
2591
2592 void
print(class cl_commander_base * c)2593 cl_error_unknown_code::print(class cl_commander_base *c)
2594 {
2595 //FILE *f= c->get_out();
2596 /*cmd_fprintf(f,*/c->dd_printf("%s: unknown instruction code at ", get_type_name());
2597 if (uc->rom)
2598 {
2599 /*cmd_fprintf(f,*/c->dd_printf(uc->rom->addr_format, PC);
2600 /*cmd_fprintf(f,*/c->dd_printf(" (");
2601 /*cmd_fprintf(f,*/c->dd_printf(uc->rom->data_format, uc->rom->get(PC));
2602 /*cmd_fprintf(f,*/c->dd_printf(")");
2603 }
2604 else
2605 /*cmd_fprintf(f,*/c->dd_printf("0x%06x", AU(PC));
2606 /*cmd_fprintf(f,*/c->dd_printf("\n");
2607 }
2608
2609
cl_uc_error_registry(void)2610 cl_uc_error_registry::cl_uc_error_registry(void)
2611 {
2612 class cl_error_class *prev = uc_error_registry.find("non-classified");
2613 prev = register_error(new cl_error_class(err_error, "unknown_code", prev, ERROR_OFF));
2614 }
2615
2616 /* End of uc.cc */
2617