2 * Simulator of microcontrollers (uc.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
10 /* This file is part of microcontroller simulator: ucsim.
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.
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.
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
28 //#include "ddconfig.h"
35 //#include "i_string.h"
42 //#include "newcmdcl.h"
43 //#include "cmdutil.h"
46 #include "cmd_getcl.h"
47 #include "cmd_setcl.h"
48 #include "cmd_infocl.h"
49 #include "cmd_timercl.h"
50 #include "cmd_statcl.h"
51 #include "cmd_memcl.h"
52 #include "cmd_execcl.h"
64 static class cl_uc_error_registry uc_error_registry
;
70 cl_ticker::cl_ticker(int adir
, enum ticker_type atype
, const char *aname
, bool auser
)
80 cl_ticker::~cl_ticker(void) {}
83 cl_ticker::tick(int nr
, double time
)
98 cl_ticker::dump(int nr
, class cl_console_base
*con
)
100 const char *type_names
[] = { "", ",ISR", ",IDLE", ",HALT" };
102 con
->dd_printf("timer #%d(\"%s\") %s%s %.15f sec (%lu clks)\n",
103 nr
, get_name("unnamed"),
104 (run
? "ON" : "OFF"),
114 cl_xtal_option::cl_xtal_option(class cl_uc
*the_uc
):
121 cl_xtal_option::option_changed(void)
126 option
->get_value(&d
);
130 cl_stop_selfjump_option::cl_stop_selfjump_option(class cl_uc
*the_uc
):
137 cl_stop_selfjump_option::init(void)
140 create(uc
, bool_opt
, "selfjump_stop", "Stop when jump branches to itself");
145 cl_stop_selfjump_option::option_changed(void)
148 option
->get_value(&b
);
149 uc
->stop_selfjump
= b
;
153 cl_analyzer_opt::cl_analyzer_opt(class cl_uc
*Iuc
):
154 cl_bool_option(Iuc
, "analyzer", "Analyze and label code")
160 cl_analyzer_opt::set_value(const char *s
)
163 cl_bool_option::set_value(s
);
166 if (uc
->analyser_opt
) uc
->analyser_opt
->set_raw(b
);
170 cl_analyser_opt::cl_analyser_opt(class cl_uc
*Iuc
):
171 cl_bool_option(Iuc
, "analyser", "Analyse and label code")
177 cl_analyser_opt::set_value(const char *s
)
180 cl_bool_option::set_value(s
);
183 if (uc
->analyzer_opt
) uc
->analyzer_opt
->set_raw(b
);
188 cl_time_measurer::cl_time_measurer(class cl_uc
*the_uc
):
196 cl_time_measurer::set_reach(unsigned long val
)
202 cl_time_measurer::from_now(unsigned long val
)
204 set_reach(now() + val
);
208 cl_time_measurer::reached()
215 cl_time_measurer::now()
221 /* value of xtal clock */
227 return uc
->ticks
->get_ticks();
231 /* value of virtual clocks */
237 return uc
->vc
.fetch
+ uc
->vc
.rd
+ uc
->vc
.wr
;
241 /* value of fetches */
261 /* value of writes */
271 /* OMF file record */
273 cl_omf_rec::cl_omf_rec(void):
284 cl_omf_rec::~cl_omf_rec(void)
291 cl_omf_rec::g(cl_f
*f
)
293 unsigned char c
= f
->get_c();
299 cl_omf_rec::pick_word(int i
)
313 cl_omf_rec::pick_str(int i
)
333 cl_omf_rec::read(cl_f
*f
)
359 rec
= (u8_t
*)malloc(len
);
360 for (i
= 0; i
< len
; i
++)
376 cl_exec_hist::cl_exec_hist(class cl_uc
*auc
):
381 hist
= (struct t_hist_elem
*)malloc(sizeof(struct t_hist_elem
) * len
);
385 cl_exec_hist::~cl_exec_hist(void)
392 cl_exec_hist::init(void)
398 cl_exec_hist::put(void)
406 if (hist
[h
].addr
== pc
)
421 cl_exec_hist::list(class cl_console_base
*con
, bool inc
, int nr
)
443 l
= con
->dd_cprintf("dump_address", "0x%06x", AU(hist
[p
].addr
));
447 l
= uc
->print_disass(hist
[p
].addr
, con
, false);
451 l
++; con
->dd_printf(" ");
453 l
++, con
->dd_printf(" ");
454 con
->dd_printf("(%d times)", hist
[p
].nr
);
456 con
->dd_printf("\n");
472 con
->dd_color("answer");
478 cl_exec_hist::keep(int nr
)
484 while (get_used() > nr
)
489 cl_exec_hist::get_used()
499 cl_exec_hist::get_insts()
519 * Abstract microcontroller
520 ******************************************************************************
523 cl_uc::cl_uc(class cl_sim
*asim
):
530 //mems= new cl_list(MEM_TYPES, 1);
531 memchips
= new cl_memory_list(this, "memchips");
532 address_spaces
= new cl_memory_list(this, "address_spaces");
533 //address_decoders= new cl_list(2, 2);
537 //options= new cl_list(2, 2);
538 //for (i= MEM_ROM; i < MEM_TYPES; i++) mems->add(0);
539 xtal_option
= new cl_xtal_option(this);
541 stop_selfjump_option
= new cl_stop_selfjump_option(this);
542 stop_selfjump_option
->init();
545 counters
= new cl_list(2, 2, "counters");
546 ticks
= new cl_ticker(+1, TICK_ANY
, "time", false);
547 add_counter(ticks
, ticks
->get_name());
548 isr_ticks
= new cl_ticker(+1, TICK_INISR
, "isr", false);
549 add_counter(isr_ticks
, isr_ticks
->get_name());
550 idle_ticks
= new cl_ticker(+1, TICK_IDLE
, "idle", false);
551 add_counter(idle_ticks
, idle_ticks
->get_name());
552 halt_ticks
= new cl_ticker(+1, TICK_HALT
, "halt", false);
553 add_counter(halt_ticks
, halt_ticks
->get_name());
554 it_levels
= new cl_list(2, 2, "it levels");
555 it_sources
= new cl_irqs(2, 2);
556 class it_level
*il
= new it_level(-1, 0, 0, 0);
558 stack_ops
= new cl_list(2, 2, "stack operations");
559 errors
= new cl_list(2, 2, "errors in uc");
560 events
= new cl_list(2, 2, "events in uc");
564 hist
= new cl_exec_hist(this);
578 events
->disconn_all();
589 delete address_spaces
;
591 //delete address_decoders;
602 set_name("controller");
604 if (xtal_option
->use("xtal"))
605 x
= xtal_option
->get_value(xtal
);
609 stop_selfjump
= false;
610 stop_selfjump_option
->option
->set_value(stop_selfjump
);
612 analyzer_opt
= new cl_analyzer_opt(this);
613 analyzer_opt
->init();
614 analyzer_opt
->set_raw(analyzer
);
615 analyser_opt
= new cl_analyser_opt(this);
616 analyser_opt
->init();
617 analyser_opt
->set_raw(analyzer
);
618 application
->options
->add(analyzer_opt
);
619 application
->options
->add(analyser_opt
);
620 vars
= new cl_var_list();
622 // Some app level vars:
623 reg_cell_var(&(application
->cperiod
),
624 &(application
->period
),
626 "Cycles between input checks");
627 reg_cell_var(&(application
->ccyc
),
630 "Nr of cycles executed during simulation");
631 reg_cell_var(&cPC
, &PC
, "PC", "Program counter");
635 rom
= address_space("rom"/*MEM_ROM_ID*/);
636 ebrk
= new brk_coll(2, 2, rom
);
637 fbrk
= new brk_coll(2, 2, rom
);
638 displays
= new cl_display_list(2, 2, "displays");
639 fbrk
->Duplicates
= false;
644 class cl_cmdset
*cs
= sim
->app
->get_commander()->cmdset
;
651 for (i
= 0; i
< sim
->app
->in_files
->count
; i
++)
653 const char *fname
= (const char *)(sim
->app
->in_files
->at(i
));
655 if ((l
= read_hex_file(fname
)) >= 0)
657 /*sim->app->get_commander()->all_*/printf("%ld words read from %s\n",
665 cl_uc::id_string(void)
667 return("unknown microcontroller");
679 isr_ticks
->set(0, 0);
680 idle_ticks
->set(0, 0);
681 halt_ticks
->set(0, 0);
682 vc
.inst
= vc
.fetch
= vc
.rd
= vc
.wr
= 0;
683 /*FIXME should we clear user counters?*/
684 il
= (class it_level
*)(it_levels
->top());
688 il
= (class it_level
*)(it_levels
->pop());
690 il
= (class it_level
*)(it_levels
->top());
695 stack_ops
->free_all();
698 for (i
= 0; i
< hws
->count
; i
++)
700 class cl_hw
*hw
= (class cl_hw
*)(hws
->at(i
));
706 cl_uc::reg_cell_var(class cl_memory_cell
*cell
,
708 chars vname
, chars vdesc
)
718 vars
->add(v
= new cl_cvar(vname
, cell
, vdesc
));
726 cl_uc::mk_cvar(class cl_memory_cell
*cell
, chars vname
, chars vdesc
,
730 vars
->add(v
= new cl_cvar(vname
, cell
, vdesc
));
740 cl_uc::make_memories(void)
745 cl_uc::make_variables(void)
747 class cl_address_space
*as
;
748 class cl_option
*o
= sim
->app
->options
->get_option("var_size");
756 class cl_address_decoder
*ad
;
757 class cl_memory_chip
*chip
;
761 variables
= as
= new cl_address_space("variables", 0, l
, 32);
763 address_spaces
->add(as
);
765 chip
= new cl_chip32("variable_storage", l
, 32);
768 ad
= new cl_address_decoder(variables
, chip
, 0, l
-1, 0);
770 variables
->decoders
->add(ad
);
773 for (i
= 0; i
< l
; i
++)
774 variables
->set(i
, 0);
779 cl_uc::get_mem_size(char *id)
781 class cl_memory *m= memory(id);
782 return(m?(m->get_size()):0);
786 cl_uc::get_mem_width(char *id)
788 class cl_memory *m= memory(id);
789 return(m?(m->width):8);
793 cl_uc::make_cpu_hw(void)
799 cl_uc::mk_hw_elements(void)
803 init_add_hw(h
= new cl_simulator_interface(this));
804 init_add_hw(h
= new cl_vcd(this, 0, "vcd"));
808 cl_uc::build_cmdset(class cl_cmdset
*cmdset
)
811 class cl_super_cmd
*super_cmd
;
812 class cl_cmdset
*cset
;
814 cmdset
->add(cmd
= new cl_state_cmd("state", 0));
818 cmdset
->add(cmd
= new cl_statistic_cmd("statistic", 0));
822 cmdset
->add(cmd
= new cl_file_cmd("file", 0));
824 cmd
->add_name("load");
826 cmdset
->add(cmd
= new cl_dl_cmd("download", 0));
830 cmdset
->add(cmd
= new cl_check_cmd("check", 0));
833 cmdset
->add(cmd
= new cl_pc_cmd("pc", 0));
836 cmdset
->add(cmd
= new cl_reset_cmd("reset", 0));
839 cmdset
->add(cmd
= new cl_tick_cmd("tick", 0));
842 cmdset
->add(cmd
= new cl_dump_cmd("dump", true));
846 cmdset
->add(cmd
= new cl_dch_cmd("dch", true));
849 cmdset
->add(cmd
= new cl_dc_cmd("dc", true));
852 cmdset
->add(cmd
= new cl_disassemble_cmd("disassemble", true));
855 cmdset
->add(cmd
= new cl_fill_cmd("fill", 0));
858 cmdset
->add(cmd
= new cl_where_cmd("where", 0));
861 cmdset
->add(cmd
= new cl_Where_cmd("Where", 0));
864 cmdset
->add(cmd
= new cl_hole_cmd("hole", 0));
867 cmdset
->add(cmd
= new cl_break_cmd("break", 0));
870 cmdset
->add(cmd
= new cl_tbreak_cmd("tbreak", 0));
873 cmdset
->add(cmd
= new cl_clear_cmd("clear", 0));
876 cmdset
->add(cmd
= new cl_delete_cmd("delete", 0));
879 cmdset
->add(cmd
= new cl_commands_cmd("commands", 0));
882 cmdset
->add(cmd
= new cl_display_cmd("display", 0));
885 cmdset
->add(cmd
= new cl_undisplay_cmd("undisplay", 0));
889 super_cmd
= (class cl_super_cmd
*)(cmdset
->get_cmd("get"));
891 cset
= super_cmd
->commands
;
893 cset
= new cl_cmdset();
896 cset
->add(cmd
= new cl_get_sfr_cmd("sfr", 0));
898 /*cset->add(cmd= new cl_get_option_cmd("option", 0));
902 cmdset
->add(cmd
= new cl_super_cmd("get", 0, cset
));
909 super_cmd
= (class cl_super_cmd
*)(cmdset
->get_cmd("set"));
911 cset
= super_cmd
->commands
;
913 cset
= new cl_cmdset();
916 cset
->add(cmd
= new cl_set_mem_cmd("memory", 0));
917 cmd
->add_name("bits");
919 cset
->add(cmd
= new cl_set_hw_cmd("hardware", 0));
924 cmdset
->add(cmd
= new cl_super_cmd("set", 0, cset
));
931 super_cmd
= (class cl_super_cmd
*)(cmdset
->get_cmd("info"));
933 cset
= super_cmd
->get_subcommands();
935 cset
= new cl_cmdset();
938 cset
->add(cmd
= new cl_info_bp_cmd("breakpoints", 0));
941 cset
->add(cmd
= new cl_info_reg_cmd("registers", 0));
943 cset
->add(cmd
= new cl_info_hw_cmd("hardware", 0));
948 cset->add(cmd= new cl_info_stack_cmd("stack", 0,
949 "info stack Status of stack of the CPU",
950 "long help of info stack"));
953 cset
->add(cmd
= new cl_info_memory_cmd("memory", 0));
955 cset
->add(cmd
= new cl_info_var_cmd("variables", 0));
957 cmd
->add_name("vars");
958 cset
->add(cmd
= new cl_hist_info_cmd("history", 0));
961 cmdset
->add(cmd
= new cl_super_cmd("info", 0, cset
));
968 super_cmd
= (class cl_super_cmd
*)(cmdset
->get_cmd("timer"));
970 cset
= super_cmd
->get_subcommands();
972 cset
= new cl_cmdset();
975 cset
->add(cmd
= new cl_timer_add_cmd("add", 0));
977 cmd
->add_name("create");
978 cmd
->add_name("make");
979 cset
->add(cmd
= new cl_timer_delete_cmd("delete", 0));
981 cmd
->add_name("remove");
982 cset
->add(cmd
= new cl_timer_get_cmd("get", 0));
984 cset
->add(cmd
= new cl_timer_run_cmd("run", 0));
986 cmd
->add_name("start");
987 cset
->add(cmd
= new cl_timer_stop_cmd("stop", 0));
989 cset
->add(cmd
= new cl_timer_value_cmd("set", 0));
991 cmd
->add_name("value");
992 cset
->add(cmd
= new cl_timer_list_cmd("list", 0));
995 cmdset
->add(cmd
= new cl_super_cmd("timer", 0, cset
));
1002 class cl_super_cmd
*mem_create
, *mem_remove
;
1003 class cl_cmdset
*mem_create_cset
, *mem_remove_cset
;
1004 super_cmd
= (class cl_super_cmd
*)(cmdset
->get_cmd("memory"));
1006 cset
= super_cmd
->get_subcommands();
1008 cset
= new cl_cmdset();
1012 cset->add(cmd= new cl_memory_cmd("_no_parameters_", 0));
1015 mem_create
= (class cl_super_cmd
*)cset
->get_cmd("create");
1017 mem_create_cset
= mem_create
->get_subcommands();
1019 mem_create_cset
= new cl_cmdset();
1020 mem_create_cset
->init();
1023 mem_create_cset
->add(cmd
= new cl_memory_create_chip_cmd("chip", 0));
1026 mem_create_cset
->add(cmd
= new cl_memory_create_addressspace_cmd("addressspace", 0));
1028 cmd
->add_name("addrspace");
1029 cmd
->add_name("aspace");
1030 cmd
->add_name("as");
1031 cmd
->add_name("addrs");
1032 cmd
->add_name("addr");
1034 mem_create_cset
->add(cmd
= new cl_memory_create_addressdecoder_cmd("addressdecoder", 0));
1036 cmd
->add_name("addrdecoder");
1037 cmd
->add_name("adecoder");
1038 cmd
->add_name("addressdec");
1039 cmd
->add_name("addrdec");
1040 cmd
->add_name("adec");
1041 cmd
->add_name("ad");
1043 mem_create_cset
->add(cmd
= new cl_memory_create_banker_cmd("banker", 0));
1045 cmd
->add_name("bankswitcher");
1046 cmd
->add_name("banksw");
1047 cmd
->add_name("bsw");
1048 cmd
->add_name("bs");
1050 mem_create_cset
->add(cmd
= new cl_memory_create_bank_cmd("bank", 0));
1053 mem_create_cset
->add(cmd
= new cl_memory_create_bander_cmd("bander", 0));
1055 cmd
->add_name("bitbander");
1056 cmd
->add_name("bitband");
1057 cmd
->add_name("band");
1058 cmd
->add_name("bb");
1061 cset
->add(mem_create
= new cl_super_cmd("create", 0, mem_create_cset
));
1063 mem_create
->add_name("add");
1064 set_memory_create_help(mem_create
);
1066 cset
->add(cmd
= new cl_info_memory_cmd("info", 0));
1068 cset
->add(cmd
= new cl_memory_cell_cmd("cell", 0));
1071 cmdset
->add(cmd
= new cl_super_cmd("memory", 0, cset
));
1073 set_memory_help(cmd
);
1076 mem_remove
= (class cl_super_cmd
*)cset
->get_cmd("remove");
1078 mem_remove_cset
= mem_remove
->get_subcommands();
1080 mem_remove_cset
= new cl_cmdset();
1081 mem_remove_cset
->init();
1084 mem_remove_cset
->add(cmd
= new cl_memory_remove_chip_cmd("chip", 0));
1088 cset
->add(mem_remove
= new cl_super_cmd("remove", 0, mem_remove_cset
));
1090 mem_remove
->add_name("del");
1091 mem_remove
->add_name("rm");
1092 set_memory_remove_help(mem_remove
);
1095 super_cmd
= (class cl_super_cmd
*)(cmdset
->get_cmd("history"));
1097 cset
= super_cmd
->get_subcommands();
1100 cset
= new cl_cmdset();
1102 cmdset
->add(cmd
= new cl_super_cmd("history", 0, cset
));
1105 cset
->add(cmd
= new cl_hist_cmd("_no_parameters_", 0));
1107 cset
->add(cmd
= new cl_hist_info_cmd("information", 0));
1109 cset
->add(cmd
= new cl_hist_clear_cmd("clear", 0));
1111 cset
->add(cmd
= new cl_hist_list_cmd("list", 0));
1112 cmd
->add_name("print");
1115 cmdset
->add(cmd
= new cl_var_cmd("var", 0));
1117 cmd
->add_name("variable");
1118 cmdset
->add(cmd
= new cl_rmvar_cmd("rmvar", 0));
1121 cmdset
->add(cmd
= new cl_analyze_cmd("analyse", 0));
1122 cmd
->add_name("analyze");
1128 * Read/write simulated memory
1132 cl_uc::read_mem(const char *id
, t_addr addr
)
1134 class cl_address_space
*m
= address_space(id
);
1136 return(m
?(m
->read(addr
)):0);
1140 cl_uc::get_mem(const char *id
, t_addr addr
)
1142 class cl_address_space
*m
= address_space(id
);
1144 return(m
?(m
->get(addr
)):0);
1148 cl_uc::write_mem(const char *id
, t_addr addr
, t_mem val
)
1150 class cl_address_space
*m
= address_space(id
);
1153 m
->write(addr
, val
);
1157 cl_uc::set_mem(const char *id
, t_addr addr
, t_mem val
)
1159 class cl_address_space
*m
= address_space(id
);
1166 class cl_address_space
*
1167 cl_uc::address_space(const char *id
)
1174 for (i
= 0; i
< address_spaces
->count
; i
++)
1176 class cl_address_space
*m
= (cl_address_space
*)(address_spaces
->at(i
));
1178 !m
->have_real_name())
1180 if (m
->is_inamed(id
))
1186 class cl_address_space
*
1187 cl_uc::address_space(class cl_memory_cell
*cell
)
1189 return(address_space(cell
, (t_addr
*)NULL
));
1192 class cl_address_space
*
1193 cl_uc::address_space(class cl_memory_cell
*cell
, t_addr
*addr
)
1197 for (i
= 0; i
< address_spaces
->count
; i
++)
1199 class cl_address_space
*m
= (cl_address_space
*)(address_spaces
->at(i
));
1202 if (m
->is_owned(cell
, addr
))
1209 cl_uc::memory(const char *id
)
1216 for (i
= 0; i
< address_spaces
->count
; i
++)
1218 class cl_base
*b
= address_spaces
->object_at(i
);
1219 class cl_memory
*m
= (class cl_memory
*)(b
);
1221 !m
->have_real_name())
1223 if (m
->is_inamed(id
))
1226 for (i
= 0; i
< memchips
->count
; i
++)
1228 class cl_memory
*m
= (cl_memory
*)(memchips
->at(i
));
1230 !m
->have_real_name())
1232 if (m
->is_inamed(id
))
1239 cl_uc::remove_chip(class cl_memory
*chip
)
1241 class cl_address_space
*as
;
1242 class cl_address_decoder
*ad
;
1245 i
= memchips
->index_of(chip
, &idx
);
1248 for (i
= 0; i
< address_spaces
->get_count(); i
++)
1250 as
= (class cl_address_space
*)(address_spaces
->at(i
));
1252 class cl_list bankers
;
1254 while (j
< as
->decoders
->get_count())
1256 for (j
= 0; j
< as
->decoders
->get_count(); j
++)
1258 t_addr as_start
, as_end
;
1259 ad
= (class cl_address_decoder
*)(as
->decoders
->at(j
));
1260 as_start
= ad
->as_begin
;
1262 if (ad
->memchip
== chip
)
1264 as
->undecode_area(NULL
, as_start
, as_end
, NULL
);
1267 if (ad
->is_banker())
1269 if (ad
->uses_chip(chip
))
1276 if (bankers
.count
> 0)
1279 for (i
= 0; i
< bankers
.count
; i
++)
1281 class cl_address_decoder
*ad
;
1282 ad
= (class cl_address_decoder
*)(bankers
.at(i
));
1283 as
->decoders
->disconn(ad
);
1286 bankers
.disconn_all();
1289 memchips
->disconn(chip
);
1295 ReadInt(cl_f
*f
, bool *ok
, int bytes
)
1321 l
= l
*256 + strtol(s2
, NULL
, 16);
1330 * Reading intel hexa file into EROM
1331 *____________________________________________________________________________
1333 * If parameter is a NULL pointer, this function reads data from `cmd_in'
1338 cl_uc::set_rom(t_addr addr
, t_mem val
)
1340 t_addr size
= rom
->get_size();
1343 rom
->download(addr
, val
);
1349 class cl_banker
*d
= (class cl_banker
*)(rom
->get_decoder_of(caddr
));
1352 if (!d
->is_banker())
1356 d
->switch_to(bank
, NULL
);
1357 rom
->download(caddr
, val
);
1366 cl_uc::read_hex_file(const char *nam
)
1372 fprintf(stderr
, "cl_uc::read_hex_file File name not specified\n");
1376 if ((f
= /*fopen*/mk_io(nam
, "r")) == NULL
)
1378 fprintf(stderr
, "Can't open `%s': %s\n", nam
, strerror(errno
));
1381 long l
= read_hex_file(f
);
1387 cl_uc::read_hex_file(cl_console_base
*con
)
1395 long l
= read_hex_file(f
);
1400 cl_uc::read_hex_file(cl_f
*f
)
1403 long written
= 0, recnum
= 0;
1405 uint base
= 0; // extended address, added to every address
1406 uchar dnum
; // data number
1407 uchar rtyp
=0; // record type
1408 uint addr
= 0; // address
1409 uchar rec
[300]; // data record
1410 uchar sum
; // checksum
1411 uchar chk
; // check
1415 uchar lows
[4]= { 0, 0, 0, 0 };
1419 sim
->app
->get_commander()->
1420 dd_printf("No ROM address space to read in.\n");
1424 //memset(inst_map, '\0', sizeof(inst_map));
1429 while (((c
= /*getc(f)*/f
->get_c()) != ':') &&
1430 (/*c != EOF*/!f
->eof()));
1433 fprintf(stderr
, ": not found\n");
1437 dnum
= ReadInt(f
, &ok
, 1);
1439 addr
= ReadInt(f
, &ok
, 2);
1440 chk
+= (addr
& 0xff);
1441 chk
+= ((addr
>> 8) & 0xff);
1442 rtyp
= ReadInt(f
, &ok
, 1);
1444 for (i
= 0; ok
&& (i
< dnum
); i
++)
1446 rec
[i
]= ReadInt(f
, &ok
, 1);
1451 sum
= ReadInt(f
, &ok
, 1);
1454 if (((sum
+ chk
) & 0xff) == 0)
1460 for (i
= 0; i
< dnum
; i
++)
1462 if (rom
->width
<= 8)
1464 set_rom(base
+addr
, rec
[i
]);
1468 else if (rom
->width
<= 16)
1472 case 0: lows
[0]= rec
[i
]; get_low
++; break;
1473 case 1: lows
[1]= rec
[i
];
1474 set_rom(base
+addr
, (lows
[1]*256)+lows
[0]);
1481 else if (rom
->width
<= 32)
1485 case 0: lows
[0]= rec
[i
]; get_low
++; break;
1486 case 1: lows
[1]= rec
[i
]; get_low
++; break;
1487 case 2: lows
[2]= rec
[i
]; get_low
++; break;
1488 case 3: lows
[3]= rec
[i
];
1495 lows
[3]= lows
[2]= lows
[1]= lows
[0]= 0;
1507 base
= (rec
[0]*256+rec
[1]) << 16;
1512 fprintf(stderr
, "Unknown record type %d(0x%x)\n",
1516 fprintf(stderr
, "Checksum error (%x instead of %x) in "
1517 "record %ld.\n", chk
, sum
, recnum
);
1520 fprintf(stderr
, "Read error in record %ld.\n", recnum
);
1525 for (i
= get_low
; i
<4; i
++)
1538 cl_uc::read_omf_file(cl_f
*f
)
1541 class cl_omf_rec rec
;
1544 if (rec
.type
== 0x06)
1547 u16_t addr
= rec
.pick_word(1);
1551 set_rom(addr
+i
, rec
.rec
[i
]);
1561 cl_uc::read_asc_file(cl_f
*f
)
1564 chars line
= chars();
1569 while ((c
= f
->get_c()) &&
1574 if ((c
=='\n') || (c
=='\r'))
1578 chars word
= chars();
1583 word
= line
.token(" ");
1587 t_mem d
= chars(s
).htoi();//strtoll(s, 0, 16);
1599 if ((c
=='\n') || (c
=='\r'))
1612 cl_uc::read_p2h_file(cl_f
*f
, bool just_check
)
1614 chars line
= chars();
1617 while ((c
= f
->get_c()) &&
1620 if ((c
=='\n') || (c
=='\r'))
1624 chars w1
= line
.token(" \t");
1625 chars w2
= line
.token(" \t");
1626 chars w3
= line
.token(" \t");
1627 if (w1
.nempty() && w2
.nempty() && w3
.nempty())
1629 if ((w2
== "//C") || (w2
== "//I"))
1631 t_mem v
= w1
.htoi();//strtol(w1.c_str(), 0, 16);
1632 t_addr a
= w3
.htoi();//strtol(w3.c_str(), 0, 16);
1635 t_mem mv
= rom
->read(a
);
1638 application
->dd_printf("Diff at %08x, FILE=%08x MEM=%08x\n",
1639 AU32(a
), MU32(v
), MU32(mv
));
1656 cl_uc::read_cdb_file(cl_f
*f
)
1658 class cl_cdb_recs
*fns
= new cl_cdb_recs();
1662 class cl_cdb_rec
*r
;
1672 if ((lc
[1] == ':') &&
1676 chars n
= ln
.token("$");
1677 if ((r
= fns
->rec(n
)) != NULL
)
1680 v
= vars
->add(n
, rom
, r
->addr
, "");
1681 v
->set_by(VBY_DEBUG
);
1686 fns
->add(new cl_cdb_rec(n
));
1690 else if (lc
[0] == 'L')
1694 if ((ln
[1] == ':') &&
1698 chars n
= ln
.token("$");
1699 chars t
= ln
.token(":");
1701 t_addr a
= t
.htoi();//strtol(t.c_str(), 0, 16);
1702 if ((r
= fns
->rec(n
)) != NULL
)
1706 v
= vars
->add(n
, rom
, a
, "");
1707 v
->set_by(VBY_DEBUG
);
1711 fns
->add(new cl_cdb_rec(n
, a
));
1722 static bool is_area(chars w1
, chars w2
, chars w3
)
1724 if (w1
.empty() || w2
.empty() || w3
.empty())
1735 static bool is_code_seg(chars wlast
)
1737 return wlast
== "(REL,CON,CODE)";
1740 static bool is_ncode_seg(chars w1
, chars wlast
)
1742 return (wlast
== "(REL,CON)")
1750 static bool is_addr(chars w
)
1753 if (l
!= 8) return false;
1754 const char *s
= w
.c_str();
1756 for (i
= 0; i
<l
; i
++)
1757 if (!isxdigit(s
[i
])) return false;
1762 cl_uc::read_map_file(cl_f
*f
)
1766 chars s
, w1
, w2
, w3
, wlast
, w
;
1767 enum { s_wait_area
, s_wait_seginfo
, s_wait_sym
, s_wait_nsym
} stat
;
1777 w1
= ln
.token(" \t\v");
1778 if (w1
.nempty()) wlast
= w1
;
1779 w2
= ln
.token(" \t\v");
1780 if (w2
.nempty()) wlast
= w2
;
1781 w3
= ln
.token(" \t\v");
1782 if (w3
.nempty()) wlast
= w3
;
1783 w
= ln
.token(" \t\v");
1787 w
= ln
.token(" \t\v");
1792 if (is_area(w1
, w2
, w3
))
1793 stat
= s_wait_seginfo
;
1795 case s_wait_seginfo
:
1796 if (is_code_seg(wlast
))
1798 else if (is_ncode_seg(w1
, wlast
))
1802 if (is_area(w1
, w2
, w3
))
1803 stat
= s_wait_seginfo
;
1806 if ((w1
== "C:") && is_addr(w2
) && (w3
.c(0) == '_'))
1808 w3
= &(w3
.c_str()[1]);
1809 t_addr a
= w2
.htoi();//strtol(w2.c_str(), NULL, 16);
1810 //printf("%s %08x\n", w3.c_str(), AU(a));
1811 v
= vars
->add(w3
, rom
, a
, "");
1812 v
->set_by(VBY_DEBUG
);
1818 if (is_area(w1
, w2
, w3
))
1819 stat
= s_wait_seginfo
;
1822 if (is_addr(w1
) && (w2
.c(0) == '_'))
1824 w2
= &(w2
.c_str()[1]);
1825 t_addr a
= w1
.htoi();//strtol(w1.c_str(), NULL, 16);
1826 //printf("%s %08x\n", w2.c_str(), AU(a));
1827 v
= vars
->add(w2
, rom
, a
, "");
1828 v
->set_by(VBY_DEBUG
);
1838 static int h1(const char *s
, int p
)
1853 static int h2(const char *s
, int p
)
1856 if (isxdigit(s
[p
]) && isxdigit(s
[p
+1]))
1864 static t_addr
a16(const char *s
, int p
)
1873 static t_addr
a24(const char *s
, int p
)
1884 static t_addr
a32(const char *s
, int p
)
1897 static int s19(class cl_uc
*uc
, t_addr a
, const char *s
, int p
, int data_bytes
)
1902 while (b
< data_bytes
)
1914 cl_uc::read_s19_file(cl_f
*f
)
1918 long int written
= 0;
1924 const char *s
= line
.c_str();
1927 if (line
.length() < 4)
1930 if (line
.length() < 4+cnt
*2)
1932 int b
= 0, sum
= 0, p
= 2;
1942 int chk
= h2(s
, 2+cnt
*2);
1954 written
+= s19(this, a
, s
, p
, cnt
-2-1);
1959 written
+= s19(this, a
, s
, p
, cnt
-3-1);
1964 written
+= s19(this, a
, s
, p
, cnt
-4-1);
1978 cl_uc::find_loadable_file(chars nam
)
1989 c
= chars("", "%s.p2h", nam
.c_str());
1994 c
= chars("", "%s.asc", nam
.c_str());
1999 c
= chars("", "%s.ihx", nam
.c_str());
2004 c
= chars("", "%s.hex", nam
.c_str());
2009 c
= chars("", "%s.ihex", nam
.c_str());
2014 c
= chars("", "%s.s19", nam
.c_str());
2020 c
= chars("", "%s.omf", nam
.c_str());
2031 cl_uc::read_file(chars nam
, class cl_console_base
*con
, bool just_check
)
2033 cl_f
*f
= find_loadable_file(nam
);
2039 con
->dd_printf("no loadable file found (%s)\n", nam
.c_str());
2041 printf("no loadable file found (%s)\n", nam
.c_str());
2044 if (!application
->quiet
)
2045 printf("Loading from %s\n", f
->get_file_name());
2048 l
= read_p2h_file(f
, just_check
);
2049 if (!application
->quiet
)
2050 printf("%ld words read from %s\n", l
, f
->get_fname());
2054 l
= read_asc_file(f
);
2055 if (!application
->quiet
)
2056 printf("%ld words read from %s\n", l
, f
->get_fname());
2060 l
= read_hex_file(f
);
2061 if (!application
->quiet
)
2062 printf("%ld words read from %s\n", l
, f
->get_fname());
2064 else if (is_s19_file(f
))
2066 l
= read_s19_file(f
);
2067 if (!application
->quiet
)
2068 printf("%ld words read from %s\n", l
, f
->get_fname());
2070 else if (is_omf_file(f
))
2072 l
= read_omf_file(f
);
2073 if (!application
->quiet
)
2074 printf("%ld words read from %s\n", l
, f
->get_fname());
2076 else if (is_cdb_file(f
))
2078 l
= read_cdb_file(f
);
2079 if (!application
->quiet
)
2080 printf("%ld symbols read from %s\n", l
, f
->get_fname());
2082 else if (is_map_file(f
))
2084 l
= read_map_file(f
);
2085 if (!application
->quiet
)
2086 printf("%ld symbols read from %s\n", l
, f
->get_fname());
2088 if (strcmp(nam
, f
->get_fname()) != 0)
2092 cl_f
*c
= mk_io(n
, "r");
2095 l
= read_cdb_file(c
);
2096 if (!application
->quiet
)
2097 printf("%ld symbols read from %s\n", l
, c
->get_fname());
2101 if (strcmp(nam
, f
->get_fname()) != 0)
2105 cl_f
*c
= mk_io(n
, "r");
2108 l
= read_map_file(c
);
2109 if (!application
->quiet
)
2110 printf("%ld symbols read from %s\n", l
, c
->get_fname());
2123 cl_uc::set_analyzer(bool val
)
2131 cl_uc::analyze_init(void)
2133 // Forget everything we knew previously.
2134 for (t_addr addr
= rom
->get_start_address(); addr
< rom
->highest_valid_address(); addr
++)
2138 while (i
< vars
->by_name
.count
)
2140 class cl_cvar
*v
= vars
->by_name
.at(i
);
2141 if (*(v
->get_name()) == '.')
2142 vars
->del(v
->get_name());
2152 cl_uc::analyze_start(void)
2154 class cl_var
*v
= new cl_var(".reset", rom
, reset_addr(),
2155 chars("Auto-generated by analyze"), -1, -1);
2158 v
->set_by(VBY_ANALYZE
);
2164 cl_uc::analyze(t_addr addr
)
2168 // If we jumped we should make sure its labeled. However we don't know if the
2169 // target has a valid instruction and only a microprocessor specific analyze
2170 // implementation can follow the execution path. So we tell a white lie.
2171 bool was_inst
= inst_at(PC
);
2174 if (PC
!= addr
+ inst_length(addr
))
2175 analyze_jump(addr
, PC
, 'j');
2182 cl_uc::analyze_jump(t_addr addr
, t_addr target
, char type
, unsigned int bit
)
2184 // If the target isn't already labeled we'll create one ourselves.
2186 if (!vars
->by_addr
.search(rom
, target
, -1, -1, var_i
) &&
2187 !vars
->by_addr
.search(rom
, target
, rom
->width
, 0, var_i
))
2189 const char *var_name
= "";
2190 const char *suffix
= "";
2194 case 's': // subroutine call
2200 suffix
= (type
== 't' ? "_isset" : "_unset");
2204 case 0: var_name
= "bit0"; break;
2205 case 1: var_name
= "bit1"; break;
2206 case 2: var_name
= "bit2"; break;
2207 case 3: var_name
= "bit3"; break;
2208 case 4: var_name
= "bit4"; break;
2209 case 5: var_name
= "bit5"; break;
2210 case 6: var_name
= "bit6"; break;
2211 case 7: var_name
= "bit7"; break;
2216 var_name
= (target
<= addr
? "loop" : "label");
2220 chars
label("", ".%s%s$%u", var_name
, suffix
, label_index
++);
2221 class cl_var
*v
= new cl_var(label
, rom
, target
, chars("Auto-generated by analyze"), -1, -1);
2224 v
->set_by(VBY_ANALYZE
);
2227 // If we didn't know the target was code we do now, but don't cross
2228 // into bankers - we don't know what bank would be selected at
2230 class cl_address_decoder
*ad
;
2231 if (!inst_at(target
) && (ad
= rom
->get_decoder_of(target
)) && !ad
->is_banker())
2236 * Handling instruction map
2238 * `inst_at' is checking if the specified address is in instruction
2239 * map and `set_inst_at' marks the address in the map and
2240 * `del_inst_at' deletes the mark. `there_is_inst' checks if there is
2241 * any mark in the map
2245 cl_uc::inst_at(t_addr addr
)
2249 return(rom
->get_cell_flag(addr
, CELL_INST
));
2253 cl_uc::set_inst_at(t_addr addr
)
2256 rom
->set_cell_flag(addr
, true, CELL_INST
);
2260 cl_uc::del_inst_at(t_addr addr
)
2263 rom
->set_cell_flag(addr
, false, CELL_INST
);
2267 cl_uc::there_is_inst(void)
2273 for (addr
= 0; rom
->valid_address(addr
) && !got
; addr
++)
2274 got
= rom
->get_cell_flag(addr
, CELL_INST
);
2280 * Manipulating HW elements of the CPU
2281 *****************************************************************************
2284 /* Register callback hw objects for mem read/write */
2287 cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
2292 if ((m= (class cl_m*)mems->at(type)))
2294 if ((l= m->read_locs->get_loc(addr)) == 0)
2296 l= new cl_memloc(addr);
2298 m->read_locs->add(l);
2303 printf("cl_uc::register_hw_read TROUBLE\n");
2307 cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
2312 cl_uc::add_hw(class cl_hw
*hw
)
2317 for (i
= 0; i
< hws
->count
; i
++)
2319 class cl_hw
*h
= (class cl_hw
*)(hws
->at(i
));
2320 h
->new_hw_adding(hw
);
2323 for (i
= 0; i
< hws
->count
; i
++)
2325 class cl_hw
*h
= (class cl_hw
*)(hws
->at(i
));
2327 h
->new_hw_added(hw
);
2332 cl_uc::init_add_hw(class cl_hw
*hw
)
2342 cl_uc::nuof_hws(void)
2347 /* Looking for a specific HW element */
2350 cl_uc::get_hw(int idx
)
2352 if (idx
>= hws
->count
)
2354 return (class cl_hw
*)(hws
->at(idx
));
2358 cl_uc::get_hw(enum hw_cath cath
, int *idx
)
2365 for (; i
< hws
->count
; i
++)
2367 hw
= (class cl_hw
*)(hws
->at(i
));
2368 if (hw
->category
== cath
)
2371 if (i
>= hws
->count
)
2379 cl_uc::get_hw(const char *id_string
, int *idx
)
2386 if (strcmp(id_string
, "cpu") == 0)
2388 for (; i
< hws
->count
; i
++)
2390 hw
= (class cl_hw
*)(hws
->at(i
));
2391 if (strstr(hw
->id_string
, id_string
) == hw
->id_string
)
2394 if (i
>= hws
->count
)
2402 cl_uc::get_hw(enum hw_cath cath
, int hwid
, int *idx
)
2409 hw
= get_hw(cath
, &i
);
2414 hw
= get_hw(cath
, &i
);
2423 cl_uc::get_hw(const char *id_string
, int hwid
, int *idx
)
2430 hw
= get_hw(id_string
, &i
);
2435 hw
= get_hw(id_string
, &i
);
2444 cl_uc::get_max_hw_id(enum hw_cath cath
)
2449 for (i
= 0; i
< hws
->count
; i
++)
2451 hw
= (class cl_hw
*)(hws
->at(i
));
2459 * Help of the command interpreter
2463 cl_uc::dis_tbl(void)
2465 static struct dis_entry empty
= { 0, 0, 0, 0, NULL
};
2470 cl_uc::disass(t_addr addr
)
2472 return strdup("uc::disass() unimplemented\n");
2476 cl_uc::print_disass(t_addr addr
, class cl_console_base
*con
, bool nl
)
2479 chars cdis
, comment
;
2482 class cl_option
*o
= sim
->app
->options
->get_option("black_and_white");
2484 if (o
) o
->get_value(&bw
);
2489 cl_vars_iterator
vi(vars
);
2490 const class cl_var
*var
= NULL
;
2491 if ((var
= vi
.first(rom
, addr
)))
2493 len
+= con
->dd_printf("\n");
2496 len
+= con
->dd_cprintf("dump_address", rom
->addr_format
, addr
);
2497 len
+= con
->dd_cprintf("answer", " ");
2498 len
+= con
->dd_cprintf("dump_label", " <%s>:\n", var
->get_name());
2499 } while ((var
= vi
.next()));
2503 dis
= disassc(addr
, &comment
);
2505 len
+= con
->dd_cprintf("dump_address", rom
->addr_format
, addr
);
2506 len
+= con
->dd_cprintf("answer", " %c", (b
? (b
->perm
== brkFIX
? 'F' : 'D') : ' '));
2507 len
+= con
->dd_cprintf("answer", "%c", inst_at(addr
)?' ':'?');
2508 l
= inst_length(addr
);
2509 for (i
= 0; i
< l
; i
++)
2511 len
+= con
->dd_printf(" ");
2512 len
+= con
->dd_cprintf("dump_number", rom
->data_format
, rom
->get(addr
+i
));
2514 int padding
= (longest_inst() - i
) * ((rom
->width
+ 3) / 4 + 1);
2515 len
+= con
->dd_printf("%*.*s", padding
, padding
, "");
2516 if (comment
.nempty())
2517 while (cdis
.len() < 25) cdis
.append(' ');
2518 len
+= con
->dd_cprintf("dump_char", " %s", cdis
.c_str());
2519 if (comment
.nempty())
2520 len
+= con
->dd_cprintf("comment", " %s", comment
.c_str());
2525 con
->dd_printf("\033[0K");
2529 while (++len
< 70) con
->dd_printf(" ");
2531 con
->dd_printf("\n");
2538 cl_uc::print_disass(t_addr addr
, class cl_console_base
*con
)
2540 return print_disass(addr
, con
, true);
2544 cl_uc::print_regs(class cl_console_base
*con
)
2546 con
->dd_printf("No registers\n");
2550 cl_uc::inst_length(t_addr addr
)
2552 struct dis_entry
*tabl
= dis_tbl();
2559 code
= rom
->get(addr
);
2560 for (i
= 0; tabl
[i
].mnemonic
&& (code
& tabl
[i
].mask
) != tabl
[i
].code
; i
++) ;
2561 return(tabl
[i
].mnemonic
?tabl
[i
].length
:1);
2565 cl_uc::inst_branch(t_addr addr
)
2567 struct dis_entry
*tabl
= dis_tbl();
2574 code
= rom
->get(addr
);
2575 for (i
= 0; tabl
[i
].mnemonic
&& (code
& tabl
[i
].mask
) != tabl
[i
].code
; i
++)
2577 return tabl
[i
].branch
;
2581 cl_uc::is_call(t_addr addr
)
2583 struct dis_entry
*tabl
= dis_tbl();
2590 code
= rom
->get(addr
);
2591 for (i
= 0; tabl
[i
].mnemonic
&& (code
& tabl
[i
].mask
) != tabl
[i
].code
; i
++)
2593 return tabl
[i
].is_call
;
2597 cl_uc::longest_inst(void)
2599 struct dis_entry
*de
= dis_tbl();
2605 if (de
->length
> max
)
2612 const class cl_var
*
2613 cl_uc::addr_name(t_addr addr
,
2614 class cl_memory
*mem
,
2618 const class cl_var
*context
)
2621 const cl_var
*var
= NULL
;
2626 if (vars
->by_addr
.search(mem
, addr
, bitnr_high
, bitnr_low
, i
))
2627 var
= vars
->by_addr
.at(i
);
2628 else if (vars
->by_addr
.search(mem
, addr
, mem
->width
- 1, 0, i
))
2629 var
= vars
->by_addr
.at(i
);
2630 else if (bitnr_high
>= 0 && vars
->by_addr
.search(mem
, addr
, -1, -1, i
))
2631 var
= vars
->by_addr
.at(i
);
2632 else if (mem
->is_address_space())
2634 cl_address_decoder
*ad
= ((cl_address_space
*)mem
)->get_decoder_of(addr
);
2637 class cl_memory
*chip
= ad
->memchip
;
2640 addr
= ad
->as_to_chip(addr
);
2642 if (vars
->by_addr
.search(chip
, addr
, bitnr_high
, bitnr_low
, i
))
2643 var
= vars
->by_addr
.at(i
);
2644 else if (vars
->by_addr
.search(chip
, addr
, chip
->width
- 1, 0, i
))
2645 var
= vars
->by_addr
.at(i
);
2646 else if (bitnr_high
>= 0 && vars
->by_addr
.search(chip
, addr
, -1, -1, i
))
2647 var
= vars
->by_addr
.at(i
);
2649 else if (vars
->by_addr
.search(mem
, addr
, -1, -1, i
))
2650 var
= vars
->by_addr
.at(i
);
2656 const char *name
= var
->get_name();
2658 // If there is a context var and its name prefixes the var for this
2659 // addr we strip the prefix off.
2661 if (context
&& (len
= strlen(context
->get_name())) &&
2662 !strncmp(name
, context
->get_name(), len
) &&
2663 (name
[len
] == '\0' || name
[len
] == '_'))
2665 if (name
[len
] == '\0')
2667 // Same as context, nothing more to add
2670 else if (name
[len
] == '_')
2672 // We don't need the prefix - we already had the context
2673 if (buf
) buf
->appendf(" <%s", &name
[len
+ 1]);
2678 // It's all significant, nothing to do with context
2679 if (buf
) buf
->appendf(" <%s", name
);
2682 if (bitnr_high
>= 0 &&
2683 (var
->bitnr_high
!= bitnr_high
|| var
->bitnr_low
!= bitnr_low
))
2685 if (bitnr_high
== bitnr_low
)
2687 if (buf
) buf
->appendf(".%d", bitnr_high
);
2691 if (buf
) buf
->appendf("[%d:%d]", bitnr_high
, bitnr_low
);
2695 if (buf
) buf
->appendf(">");
2702 cl_uc::symbol2address(char *sym
,
2703 class cl_memory
**mem
,
2711 if (vars
->by_name
.search(sym
, i
))
2713 class cl_cvar
*v
= vars
->by_name
.at(i
);
2714 /*if (v->bitnr_low >= 0)
2716 if (!v
->is_mem_var())
2721 *addr
= v
->get_addr();
2728 cl_uc::symbol2cell(char *sym
,
2729 class cl_memory_cell
**cell
)
2736 if (vars
->by_name
.search(sym
, i
))
2738 class cl_cvar
*v
= vars
->by_name
.at(i
);
2739 class cl_memory_cell
*c
= v
->get_cell();
2752 * Searching for a name in the specified table
2756 cl_uc::get_name_entry(struct name_entry tabl
[], char *name
)
2765 for (p
= name
; *p
; *p
= toupper(*p
), p
++);
2766 while (tabl
[i
].name
&&
2767 (!(tabl
[i
].cpu_type
& type
->type
) ||
2768 (strcmp(tabl
[i
].name
, name
) != 0)))
2772 if (tabl
[i
].name
!= NULL
)
2779 cl_uc::cell_name(class cl_memory_cell
*cell
, int bitnr_high
, int bitnr_low
)
2781 class cl_address_space
*as
;
2785 if (!cell
|| !(as
= address_space(cell
, &addr
)))
2788 if (vars
->by_addr
.search(as
, addr
, bitnr_high
, bitnr_low
, i
))
2789 return chars(vars
->by_addr
.at(i
)->get_name());
2791 if (bitnr_high
!= - 1 && vars
->by_addr
.search(as
, addr
, -1, -1, i
))
2793 if (bitnr_high
!= bitnr_low
)
2794 return chars("", "%s[%d:%d]", vars
->by_addr
.at(i
)->get_name(), bitnr_high
, bitnr_low
);
2796 return chars("", "%s.%d", vars
->by_addr
.at(i
)->get_name(), bitnr_low
);
2799 if (bitnr_high
== -1)
2800 return chars("", "%s_%06x", as
->get_name(), addr
);
2801 else if (bitnr_high
!= bitnr_low
)
2802 return chars("", "%s_%06x[%d:%d]", as
->get_name(), addr
, bitnr_high
, bitnr_low
);
2804 return chars("", "%s_%06x.%d", as
->get_name(), addr
, bitnr_high
);
2808 cl_uc::read_addr(class cl_memory
*m
, t_addr start_addr
)
2811 // 16 bit little endian, by default
2812 return m
->read(start_addr
) + 256*m
->read(start_addr
+1);
2816 * Messages to broadcast
2820 cl_uc::handle_event(class cl_event
&event
)
2824 case ev_address_space_added
:
2827 class cl_event_address_space_added
&e
=
2828 (class cl_event_address_space_added
&)(event
);
2829 address_space_added(e
.as
);
2837 return(pass_event_down(event
));
2845 cl_uc::mem_cell_changed(class cl_address_space *mem, t_addr addr)
2848 hws->mem_cell_changed(mem, addr);
2850 printf("JAJ uc\n");//FIXME
2855 for (i= 0; i < mems->count; i++)
2863 cl_uc::address_space_added(class cl_address_space
*as
)
2867 hws->address_space_added(as);
2869 printf("JAJ uc\n");//FIXME
2879 cl_uc::error(class cl_error
*error
)
2882 if ((error
->inst
= inst_exec
))
2887 cl_uc::check_errors(void)
2890 class cl_commander_base
*c
= sim
->app
->get_commander();
2891 bool must_stop
= false;
2895 for (i
= 0; i
< errors
->count
; i
++)
2897 class cl_error
*error
= (class cl_error
*)(errors
->at(i
));
2898 if (!error
->is_on())
2901 must_stop
= must_stop
|| (error
->get_type() & err_stop
);
2904 class cl_console_base
*con
;
2905 con
= c
->actual_console
;
2907 con
= c
->frozen_or_actual();
2910 con
->dd_printf("Erroneous instruction: ");
2911 print_disass(error
->PC
, con
);
2918 fprintf(stderr
, "no actual console, %d errors\n", errors
->count
);
2920 sim
->stop(resERROR
);
2925 * Converting bit address into real memory
2928 class cl_address_space
*
2929 cl_uc::bit2mem(t_addr bitaddr
, t_addr
*memaddr
, int *bitnr_high
, int *bitnr_low
)
2943 cl_uc::tick_hw(int cycles
)
2947 int i
;//, cpc= clock_per_cycle();
2953 for (i
= 0; i
< hc
; i
++)
2955 hw
= (class cl_hw
*)(hws
->at(i
));
2956 if ((hw
->flags
& HWF_INSIDE
) &&
2961 do_extra_hw(cycles
);
2966 cl_uc::do_extra_hw(int cycles
)
2970 cl_uc::tick(int cycles
)
2973 int i
, clocks
= cycles
* clock_per_cycle();
2974 double time
= clocks
* xtal_tick
;
2977 class it_level
*il
= (class it_level
*)(it_levels
->top());
2978 for (i
= 0; i
< counters
->count
; i
++)
2980 class cl_ticker
*t
= (class cl_ticker
*)(counters
->at(i
));
2983 if (t
->get_type() == TICK_ANY
||
2984 (il
->level
>= 0 && (t
->get_type() == TICK_INISR
)) ||
2985 (state
== stIDLE
&& (t
->get_type() == TICK_IDLE
)) ||
2986 (state
== stPD
&& (t
->get_type() == TICK_HALT
)))
2987 t
->tick(clocks
, time
);
2992 inst_ticks
+= cycles
;
2997 cl_uc::tickt(t_mem code
)
2999 i8_t
*tt
= tick_tab(code
);
3009 cl_uc::get_counter(int nr
)
3011 if (nr
>= counters
->count
)
3013 return((class cl_ticker
*)(counters
->at(nr
)));
3017 cl_uc::get_counter(const char *nam
)
3023 for (i
= 0; i
< counters
->count
; i
++)
3025 class cl_ticker
*t
= (class cl_ticker
*)(counters
->at(i
));
3028 strcmp(t
->get_name(), nam
) == 0)
3035 cl_uc::add_counter(class cl_ticker
*ticker
, int nr
)
3037 while (counters
->count
<= nr
)
3039 counters
->put_at(nr
, ticker
);
3043 cl_uc::add_counter(class cl_ticker
*ticker
, const char */
*nam*/
)
3047 if (counters
->count
< 1)
3049 for (i
= 1; i
< counters
->count
; i
++)
3051 class cl_ticker
*t
= (class cl_ticker
*)(counters
->at(i
));
3054 counters
->put_at(i
, ticker
);
3058 counters
->add(ticker
);
3062 cl_uc::del_counter(int nr
)
3066 if (nr
>= counters
->count
)
3068 if ((t
= (class cl_ticker
*)(counters
->at(0))) != 0)
3070 counters
->put_at(nr
, 0);
3074 cl_uc::del_counter(const char *nam
)
3080 for (i
= 0; i
< counters
->count
; i
++)
3082 class cl_ticker
*t
= (class cl_ticker
*)(counters
->at(i
));
3085 strcmp(t
->get_name(), nam
) == 0)
3088 counters
->put_at(i
, 0);
3095 * Fetch without checking for breakpoint hit
3106 code
= rom
->read(PC
);
3107 set_PC((PC
+1)&PCmask
);
3113 * Fetch but checking for breakpoint hit first, returns TRUE if
3114 * a breakpoint is hit
3124 if ((sim
->state
& SIM_GO
) &&
3126 (sim
->steps_done
> 0))
3133 if (rom
->get_cell_flag(PC
, CELL_FETCH_BRK
))
3134 if ((brk
= fbrk
->get_bp(PC
, &idx
)))
3137 if (brk
->perm
== brkDYNAMIC
)
3147 cl_uc::fetch(t_mem
*code
)
3149 bool ret
= do_brk();
3158 cl_uc::do_inst(void)
3168 if (res
== resINV_INST
)
3169 /* backup to start of instruction */
3175 if (res
== resGO
&& !inst_at(instPC
))
3184 if ((res
== resGO
) && (PC
== instPC
) && stop_selfjump
&& !repeating
)
3190 if ((res
== resGO
|| res
== resNOT_DONE
))
3192 int r
= do_interrupt();
3210 if (res
== resINV_INST
)
3211 /* backup to start of instruction */
3216 if ((res
== resGO
|| res
== resNOT_DONE
))
3218 int r
= do_interrupt();
3227 cl_uc::pre_inst(void)
3230 events
->disconn_all();
3237 cl_uc::pre_emu(void)
3240 events
->disconn_all();
3246 cl_uc::exec_inst(void)
3252 cl_uc::exec_inst_tab(instruction_wrapper_fn itab
[])
3257 return resBREAKPOINT
;
3258 if (itab
[c
] == NULL
)
3264 res
= itab
[c
](this, c
);
3265 if (res
== resNOT_DONE
)
3276 cl_uc::exec_inst_uctab()
3281 return resBREAKPOINT
;
3282 if (uc_itab
[c
] == NULL
)
3288 res
= (this->*uc_itab
[c
])(c
);
3289 if (res
== resNOT_DONE
)
3300 cl_uc::post_inst(void)
3303 tick_hw(inst_ticks
);
3312 cl_uc::post_emu(void)
3314 tick_hw(inst_ticks
);
3320 static FILE *pc_dump
= NULL
;
3327 if (pc_dump
==NULL
) pc_dump
= fopen("addr.txt","w");
3330 fprintf(pc_dump
,"%x 0x%06x\n", MU(application
->cyc
), AU(PC
));
3338 cl_uc::inst_unknown(t_mem code
)
3341 class cl_error_unknown_code
*e
= new cl_error_unknown_code(this);
3348 * Interrupt processing
3352 cl_uc::do_interrupt(void)
3355 bool is_en
= it_enabled();
3356 class it_level
*il
= (class it_level
*)(it_levels
->top()), *IL
= 0;
3359 for (i
= 0; i
< it_sources
->count
; i
++)
3361 class cl_it_src
*is
= (class cl_it_src
*)(it_sources
->at(i
));
3364 for (i
= 0; i
< it_sources
->count
; i
++)
3366 class cl_it_src
*is
= (class cl_it_src
*)(it_sources
->at(i
));
3378 bool A
= is
->is_active();
3379 bool E
= is
->enabled();
3380 bool P
= is
->pending();
3383 int pr
= priority_of(is
->nuof
);
3393 ap
= priority_main();
3399 if (state
== stIDLE
)
3402 sim
->app
->get_commander()->
3403 debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
3404 ticks
->get_rtime(), ticks
->get_ticks(), object_name(is
), PC
);
3405 IL
= new it_level(pr
, is
->addr
, PC
, is
);
3406 return(accept_it(IL
));
3413 cl_uc::accept_it(class it_level
*il
)
3415 it_levels
->push(il
);
3420 cl_uc::search_it_src(int cid_or_nr
)
3422 class cl_it_src
*it
;
3424 for (i
= 0; i
<it_sources
->get_count(); i
++)
3426 it
= (class cl_it_src
*)(it_sources
->at(i
));
3429 (it
->cid
!= 0 && it
->cid
== cid_or_nr
) ||
3430 (it
->cid
!= 0 && toupper(it
->cid
) == toupper(cid_or_nr
)) ||
3431 (it
->nuof
== cid_or_nr
)
3441 * Time related functions
3445 cl_uc::clocks_of_time(double t
)
3447 return (unsigned long)(t
* xtal
);
3451 cl_uc::clock_per_cycle(void)
3461 for (i
= 0; i
< hws
->count
; i
++)
3463 hw
= (class cl_hw
*)(hws
->at(i
));
3470 * Stack tracking system
3474 cl_uc::stack_write(void)
3476 stack_check_overflow();
3481 cl_uc::stack_write(t_addr sp_before
)
3483 stack_check_overflow(sp_before
);
3488 cl_uc::stack_write(class cl_stack_op
*op
)
3490 stack_check_overflow(op
);
3493 if (op
->get_op() & stack_read_operation
)
3495 class cl_error_stack_tracker_wrong_handle
*e
= new
3496 cl_error_stack_tracker_wrong_handle(false);
3501 stack_ops
->push(op
);
3505 cl_uc::stack_read(void)
3511 cl_uc::stack_read(class cl_stack_op
*op
)
3515 class cl_stack_op
*top
= (class cl_stack_op
*)(stack_ops
->top());
3517 if (op
->get_op() & stack_write_operation
)
3519 class cl_error_stack_tracker_wrong_handle
*e
= new
3520 cl_error_stack_tracker_wrong_handle(true);
3527 class cl_error
*e
= new cl_error_stack_tracker_empty(op
);
3535 if (!top
->match(op
))
3537 class cl_error
*e
= new cl_error_stack_tracker_unmatch(top
, op
);
3541 int top_size
= top
->data_size(), op_size
= op
->data_size();
3542 if (top_size
!= op_size
)
3544 application
->debug("0x%06x %d bytes to read out of stack "
3545 "but %d was pushed in last operation\n",
3546 (int)op
->get_pc(), op_size
, top_size
);
3552 top
->can_removed(op
))
3554 top
= (class cl_stack_op
*)stack_ops
->pop();
3556 top
= (class cl_stack_op
*)stack_ops
->top();
3561 application
->debug("0x%06x %d ops removed from stack-tracker "
3562 "when %s happened, top pc=0x%06x "
3563 "top before=0x%06x op after=0x%06x\n",
3564 (int)op
->get_pc(), removed
, op
->get_op_name(),
3565 top
?((int)top
->get_pc()):0,
3566 top
?((int)top
->get_before()):0,
3567 (int)op
->get_after());
3572 int ta
= top
->get_after(), oa
= op
->get_after();
3575 application
->debug("0x%06x stack still inconsistent after %s, "
3576 "%d byte(s) should be read out; top after"
3577 "=0x%06x op after=0x%06x\n",
3583 new cl_error_stack_tracker_inconsistent(op
, abs(ta
-oa
));
3593 cl_uc::stack_check_overflow(class cl_stack_op
*op
)
3598 cl_uc::stack_check_overflow(void)
3603 cl_uc::stack_check_overflow(t_addr sp_before
)
3609 * Breakpoint handling
3612 class cl_fetch_brk
*
3613 cl_uc::fbrk_at(t_addr addr
)
3617 return((class cl_fetch_brk
*)(fbrk
->get_bp(addr
, &idx
)));
3621 cl_uc::ebrk_at(t_addr addr
, char *id
)
3624 class cl_ev_brk
*eb
;
3626 for (i
= 0; i
< ebrk
->count
; i
++)
3628 eb
= (class cl_ev_brk
*)(ebrk
->at(i
));
3629 if (eb
->addr
== addr
&&
3630 !strcmp(eb
->id
, id
))
3637 cl_uc::rm_fbrk(long addr)
3642 /* Get a breakpoint specified by its number */
3645 cl_uc::brk_by_nr(int nr
)
3649 if ((bp
= fbrk
->get_bp(nr
)))
3651 if ((bp
= ebrk
->get_bp(nr
)))
3656 /* Get a breakpoint from the specified collection by its number */
3659 cl_uc::brk_by_nr(class brk_coll
*bpcoll
, int nr
)
3663 if ((bp
= bpcoll
->get_bp(nr
)))
3668 /* Remove an event breakpoint specified by its address and id */
3671 cl_uc::rm_ebrk(t_addr addr
, char *id
)
3674 class cl_ev_brk
*eb
;
3676 for (i
= 0; i
< ebrk
->count
; i
++)
3678 eb
= (class cl_ev_brk
*)(ebrk
->at(i
));
3679 if (eb
->addr
== addr
&&
3680 !strcmp(eb
->id
, id
))
3685 /* Remove a breakpoint specified by its number */
3688 cl_uc::rm_brk(int nr
)
3692 if ((bp
= brk_by_nr(fbrk
, nr
)))
3694 fbrk
->del_bp(bp
->addr
);
3697 else if ((bp
= brk_by_nr(ebrk
, nr
)))
3699 ebrk
->del_bp(ebrk
->index_of(bp
), 0);
3706 cl_uc::put_breaks(void)
3709 /* Remove all fetch and event breakpoints */
3712 cl_uc::remove_all_breaks(void)
3716 class cl_brk
*brk
= (class cl_brk
*)(fbrk
->at(0));
3717 fbrk
->del_bp(brk
->addr
);
3720 ebrk
->del_bp(ebrk
->count
-1, 0);
3724 cl_uc::make_new_brknr(void)
3726 if (brk_counter
== 0)
3727 return(brk_counter
= 1);
3728 if (fbrk
->count
== 0 &&
3730 return(brk_counter
= 1);
3731 return(++brk_counter
);
3735 cl_uc::mk_ebrk(enum brk_perm perm
, class cl_address_space
*mem
,
3736 char op
, t_addr addr
, int hit
)
3741 b
= new cl_ev_brk(mem
, make_new_brknr(), addr
, perm
, hit
, op
);
3747 cl_uc::mk_ebrk(enum brk_perm perm
, class cl_memory_cell
*cell
,
3753 b
= new cl_ev_brk(cell
, make_new_brknr(), perm
, hit
, op
);
3759 cl_uc::check_events(void)
3763 sim
->stop(resEVENTBREAK
);
3764 for (i
= 0; i
< events
->count
; i
++)
3766 class cl_ev_brk
*brk
=
3767 (class cl_ev_brk
*)(events
->object_at(i
));
3773 cl_uc::stop_when(class cl_time_measurer
*t
)
3775 if (stop_at_time
!= NULL
)
3776 delete stop_at_time
;
3783 *----------------------------------------------------------------------------
3786 cl_error_unknown_code::cl_error_unknown_code(class cl_uc
*the_uc
)
3789 classification
= uc_error_registry
.find("unknown_code");
3793 cl_error_unknown_code::print(class cl_commander_base
*c
)
3795 c
->dd_printf("%s: unknown instruction code at ", (char*)get_type_name());
3798 c
->dd_printf(uc
->rom
->addr_format
, PC
);
3800 c
->dd_printf(uc
->rom
->data_format
, uc
->rom
->get(PC
));
3804 c
->dd_printf("0x%06x", AU(PC
));
3809 cl_uc_error_registry::cl_uc_error_registry(void)
3811 class cl_error_class
*prev
= uc_error_registry
.find("non-classified");
3812 prev
= register_error(new cl_error_class(err_error
, "unknown_code", prev
, ERROR_OFF
));