PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/sdcc-230/sdcc/sim/ucsim/sim.src/uc.cc

#
C++ | 1493 lines | 1183 code | 190 blank | 120 comment | 193 complexity | 1104262c242878175e3374356f9136cf MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, GPL-3.0
  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. /* This file is part of microcontroller simulator: ucsim.
  10. UCSIM is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 2 of the License, or
  13. (at your option) any later version.
  14. UCSIM is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with UCSIM; see the file COPYING. If not, write to the Free
  20. Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  21. 02111-1307, USA. */
  22. /*@1@*/
  23. #include "ddconfig.h"
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <errno.h>
  27. #include <ctype.h>
  28. #include "i_string.h"
  29. // prj
  30. #include "globals.h"
  31. #include "utils.h"
  32. // cmd.src
  33. #include "newcmdcl.h"
  34. #include "cmduccl.h"
  35. #include "bpcl.h"
  36. #include "getcl.h"
  37. #include "setcl.h"
  38. #include "infocl.h"
  39. #include "timercl.h"
  40. // local, sim.src
  41. #include "uccl.h"
  42. #include "hwcl.h"
  43. #include "memcl.h"
  44. #include "simcl.h"
  45. #include "itsrccl.h"
  46. /*
  47. * Clock counter
  48. */
  49. cl_ticker::cl_ticker(int adir, int in_isr, char *aname)
  50. {
  51. options= TICK_RUN;
  52. if (in_isr)
  53. options|= TICK_INISR;
  54. dir= adir;
  55. ticks= 0;
  56. name= aname?strdup(aname):0;
  57. }
  58. cl_ticker::~cl_ticker(void)
  59. {
  60. if (name)
  61. free(name);
  62. }
  63. int
  64. cl_ticker::tick(int nr)
  65. {
  66. if (options&TICK_RUN)
  67. ticks+= dir*nr;
  68. return(ticks);
  69. }
  70. double
  71. cl_ticker::get_rtime(double xtal)
  72. {
  73. double d;
  74. d= (double)ticks/xtal;
  75. return(d);
  76. }
  77. void
  78. cl_ticker::dump(int nr, double xtal, class cl_console *con)
  79. {
  80. con->printf("timer #%d(\"%s\") %s%s: %g sec (%lu clks)\n",
  81. nr, name?name:"unnamed",
  82. (options&TICK_RUN)?"ON":"OFF",
  83. (options&TICK_INISR)?",ISR":"",
  84. get_rtime(xtal), ticks);
  85. }
  86. /*
  87. * Abstract microcontroller
  88. ******************************************************************************
  89. */
  90. cl_uc::cl_uc(class cl_sim *asim):
  91. cl_base()
  92. {
  93. int i;
  94. sim = asim;
  95. mems= new cl_list(MEM_TYPES, 1);
  96. hws = new cl_hws();
  97. options= new cl_list(2, 2);
  98. for (i= MEM_ROM; i < MEM_TYPES; i++)
  99. mems->add(0);
  100. ticks= new cl_ticker(+1, 0, "time");
  101. isr_ticks= new cl_ticker(+1, TICK_INISR, "isr");
  102. idle_ticks= new cl_ticker(+1, TICK_IDLE, "idle");
  103. counters= new cl_list(2, 2);
  104. it_levels= new cl_list(2, 2);
  105. it_sources= new cl_list(2, 2);
  106. class it_level *il= new it_level(-1, 0, 0, 0);
  107. it_levels->push(il);
  108. st_ops= new cl_list(2, 2);
  109. sp_max= 0;
  110. sp_avg= 0;
  111. }
  112. cl_uc::~cl_uc(void)
  113. {
  114. delete mems;
  115. delete hws;
  116. delete options;
  117. delete ticks;
  118. delete isr_ticks;
  119. delete idle_ticks;
  120. delete counters;
  121. delete fbrk;
  122. delete ebrk;
  123. delete it_levels;
  124. delete it_sources;
  125. delete st_ops;
  126. }
  127. int
  128. cl_uc::init(void)
  129. {
  130. int mc, i;
  131. cl_base::init();
  132. if (!(sim->app->args->arg_avail('X')) ||
  133. sim->app->args->get_farg('X', 0) == 0)
  134. xtal= 11059200;
  135. else
  136. xtal= sim->app->args->get_farg('X', 0);
  137. for (mc= MEM_ROM; mc < MEM_TYPES; mc++)
  138. {
  139. class cl_mem *m= mk_mem((enum mem_class)mc,
  140. get_id_string(mem_classes, mc));
  141. mems->put_at(mc, m);
  142. }
  143. ebrk= new brk_coll(2, 2, (class cl_rom *)mem(MEM_ROM));
  144. fbrk= new brk_coll(2, 2, (class cl_rom *)mem(MEM_ROM));
  145. fbrk->Duplicates= DD_FALSE;
  146. brk_counter= 0;
  147. mk_hw_elements();
  148. reset();
  149. class cl_cmdset *cs= sim->app->get_commander()->cmdset;
  150. build_cmdset(cs);
  151. for (i= 0; i < sim->app->in_files->count; i++)
  152. {
  153. char *fname= (char *)(sim->app->in_files->at(i));
  154. long l;
  155. if ((l= read_hex_file(fname)) >= 0)
  156. {
  157. sim->app->get_commander()->all_printf("%ld words read from %s\n",
  158. l, fname);
  159. }
  160. }
  161. return(0);
  162. }
  163. char *
  164. cl_uc::id_string(void)
  165. {
  166. return("unknown microcontroller");
  167. }
  168. void
  169. cl_uc::reset(void)
  170. {
  171. class it_level *il;
  172. PC= 0;
  173. state = stGO;
  174. ticks->ticks= 0;
  175. isr_ticks->ticks= 0;
  176. idle_ticks->ticks= 0;
  177. /*FIXME should we clear user counters?*/
  178. il= (class it_level *)(it_levels->top());
  179. while (il &&
  180. il->level >= 0)
  181. {
  182. il= (class it_level *)(it_levels->pop());
  183. delete il;
  184. il= (class it_level *)(it_levels->top());
  185. }
  186. sp_max= 0;
  187. sp_avg= 0;
  188. }
  189. /*
  190. * Making elements
  191. */
  192. class cl_mem *
  193. cl_uc::mk_mem(enum mem_class type, char *class_name)
  194. {
  195. class cl_mem *m;
  196. if (get_mem_size(type) <= 0)
  197. return(0);
  198. if (type == MEM_ROM)
  199. m= new cl_rom(get_mem_size(type), get_mem_width(type));
  200. else
  201. m= new cl_mem(type, get_id_string(mem_classes, type),
  202. get_mem_size(type), get_mem_width(type));
  203. m->init();
  204. return(m);
  205. }
  206. t_addr
  207. cl_uc::get_mem_size(enum mem_class type)
  208. {
  209. switch (type)
  210. {
  211. case MEM_ROM: return(0x10000);
  212. case MEM_XRAM: return(0x10000);
  213. case MEM_IRAM: return(0x100);
  214. case MEM_SFR: return(0x100);
  215. case MEM_TYPES:
  216. default: return(0);
  217. }
  218. return(0);
  219. }
  220. int
  221. cl_uc::get_mem_width(enum mem_class type)
  222. {
  223. return(8);
  224. }
  225. void
  226. cl_uc::mk_hw_elements(void)
  227. {
  228. }
  229. void
  230. cl_uc::build_cmdset(class cl_cmdset *cmdset)
  231. {
  232. class cl_cmd *cmd;
  233. class cl_cmdset *cset;
  234. cmdset->add(cmd= new cl_state_cmd("state", 0,
  235. "state State of microcontroller",
  236. "long help of state"));
  237. cmd->init();
  238. cmdset->add(cmd= new cl_file_cmd("file", 0,
  239. "file \"FILE\" Load FILE into ROM",
  240. "long help of file"));
  241. cmd->init();
  242. cmd->add_name("load");
  243. cmdset->add(cmd= new cl_dl_cmd("download", 0,
  244. "download,dl Load (intel.hex) data",
  245. "long help of download"));
  246. cmd->init();
  247. cmd->add_name("dl");
  248. cmdset->add(cmd= new cl_pc_cmd("pc", 0,
  249. "pc [addr] Set/get PC",
  250. "long help of pc"));
  251. cmd->init();
  252. cmdset->add(cmd= new cl_reset_cmd("reset", 0,
  253. "reset Reset",
  254. "long help of reset"));
  255. cmd->init();
  256. cmdset->add(cmd= new cl_dump_cmd("dump", 0,
  257. "dump memory_type [start [stop [bytes_per_line]]]\n"
  258. " Dump memory of specified type\n"
  259. "dump bit... Dump bits",
  260. "long help of dump"));
  261. cmd->init();
  262. cmdset->add(cmd= new cl_di_cmd("di", 0,
  263. "di [start [stop]] Dump Internal RAM",
  264. "long help of di"));
  265. cmd->init();
  266. cmdset->add(cmd= new cl_dx_cmd("dx", 0,
  267. "dx [start [stop]] Dump External RAM",
  268. "long help of dx"));
  269. cmd->init();
  270. cmdset->add(cmd= new cl_ds_cmd("ds", 0,
  271. "ds [start [stop]] Dump SFR",
  272. "long help of ds"));
  273. cmd->init();
  274. cmdset->add(cmd= new cl_dch_cmd("dch", 0,
  275. "dch [start [stop]] Dump code in hex form",
  276. "long help of dch"));
  277. cmd->init();
  278. cmdset->add(cmd= new cl_dc_cmd("dc", 0,
  279. "dc [start [stop]] Dump code in disass form",
  280. "long help of dc"));
  281. cmd->init();
  282. cmdset->add(cmd= new cl_disassemble_cmd("disassemble", 0,
  283. "disassemble [start [offset [lines]]]\n"
  284. " Disassemble code",
  285. "long help of disassemble"));
  286. cmd->init();
  287. cmdset->add(cmd= new cl_fill_cmd("fill", 0,
  288. "fill memory_type start end data\n"
  289. " Fill memory region with data",
  290. "long help of fill"));
  291. cmd->init();
  292. cmdset->add(cmd= new cl_where_cmd("where", 0,
  293. "where memory_type data...\n"
  294. " Case unsensitive search for data",
  295. "long help of where"));
  296. cmd->init();
  297. cmdset->add(cmd= new cl_Where_cmd("Where", 0,
  298. "Where memory_type data...\n"
  299. " Case sensitive search for data",
  300. "long help of Where"));
  301. cmd->init();
  302. cmdset->add(cmd= new cl_break_cmd("break", 0,
  303. "break addr [hit] Set fix breakpoint\n"
  304. "break mem_type r|w addr [hit]\n"
  305. " Set fix event breakpoint",
  306. "long help of break"));
  307. cmd->init();
  308. cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0,
  309. "tbreak addr [hit] Set temporary breakpoint\n"
  310. "tbreak mem_type r|w addr [hit]\n"
  311. " Set temporary event breakpoint",
  312. "long help of tbreak"));
  313. cmd->init();
  314. cmdset->add(cmd= new cl_clear_cmd("clear", 0,
  315. "clear [addr...] Clear fix breakpoint",
  316. "long help of clear"));
  317. cmd->init();
  318. cmdset->add(cmd= new cl_delete_cmd("delete", 0,
  319. "delete [nr...] Delete breakpoint(s)",
  320. "long help of clear"));
  321. cmd->init();
  322. {
  323. cset= new cl_cmdset();
  324. cset->init();
  325. cset->add(cmd= new cl_get_sfr_cmd("sfr", 0,
  326. "get sfr address...\n"
  327. " Get value of addressed SFRs",
  328. "long help of get sfr"));
  329. cmd->init();
  330. cset->add(cmd= new cl_get_option_cmd("option", 0,
  331. "get option name\n"
  332. " Get value of an option",
  333. "long help of get option"));
  334. cmd->init();
  335. }
  336. cmdset->add(cmd= new cl_super_cmd("get", 0,
  337. "get subcommand Get, see `get' command for more help",
  338. "long help of get", cset));
  339. cmd->init();
  340. {
  341. cset= new cl_cmdset();
  342. cset->init();
  343. cset->add(cmd= new cl_set_mem_cmd("memory", 0,
  344. "set memory memory_type address data...\n"
  345. " Place list of data into memory",
  346. "long help of set memory"));
  347. cmd->init();
  348. cset->add(cmd= new cl_set_bit_cmd("bit", 0,
  349. "set bit addr 0|1 Set specified bit to 0 or 1",
  350. "long help of set bit"));
  351. cmd->init();
  352. cset->add(cmd= new cl_set_port_cmd("port", 0,
  353. "set port hw data Set data connected to port",
  354. "long help of set port"));
  355. cmd->init();
  356. cset->add(cmd= new cl_set_option_cmd("option", 0,
  357. "set option name value\n"
  358. " Set value of an option",
  359. "long help of set option"));
  360. cmd->init();
  361. }
  362. cmdset->add(cmd= new cl_super_cmd("set", 0,
  363. "set subcommand Set, see `set' command for more help",
  364. "long help of set", cset));
  365. cmd->init();
  366. {
  367. cset= new cl_cmdset();
  368. cset->init();
  369. cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0,
  370. "info breakpoints Status of user-settable breakpoints",
  371. "long help of info breakpoints"));
  372. cmd->add_name("bp");
  373. cmd->init();
  374. cset->add(cmd= new cl_info_reg_cmd("registers", 0,
  375. "info registers List of integer registers and their contents",
  376. "long help of info registers"));
  377. cmd->init();
  378. cset->add(cmd= new cl_info_hw_cmd("hardware", 0,
  379. "info hardware cathegory\n"
  380. " Status of hardware elements of the CPU",
  381. "long help of info hardware"));
  382. cmd->add_name("h w");
  383. cmd->init();
  384. }
  385. cmdset->add(cmd= new cl_super_cmd("info", 0,
  386. "info subcommand Information, see `info' command for more help",
  387. "long help of info", cset));
  388. cmd->init();
  389. cmdset->add(cmd= new cl_timer_cmd("timer", 0,
  390. "timer a|d|g|r|s|v id [direction|value]\n"
  391. " Timer add|del|get|run|stop|value",
  392. "timer add|create|make id [direction] -- create a new timer\n"
  393. "timer del id -- delete a timer\n"
  394. "timer get id -- list timers\n"
  395. "timer run id -- turn a timer ON\n"
  396. "timer stop id -- turn a timer OFF\n"
  397. "timer value id val -- set value of a timer to `val'"));
  398. cmd->init();
  399. }
  400. /*
  401. * Read/write simulated memory
  402. */
  403. ulong
  404. cl_uc::read_mem(enum mem_class type, t_mem addr)
  405. {
  406. class cl_mem *m;
  407. if ((m= (class cl_mem*)mems->at(type)))
  408. return(m->read(addr));
  409. //FIXME
  410. fprintf(stderr, "cl_uc::read_mem(type= %d, 0x%06lx) TROUBLE\n", type, addr);
  411. return(0);
  412. }
  413. ulong
  414. cl_uc::get_mem(enum mem_class type, t_addr addr)
  415. {
  416. class cl_mem *m;
  417. if ((m= (class cl_mem*)mems->at(type)))
  418. return(m->get(addr));
  419. //FIXME
  420. printf("cl_uc::get_mem(type= %d, 0x%06lx) TROUBLE\n", type, addr);
  421. return(0);
  422. }
  423. void
  424. cl_uc::write_mem(enum mem_class type, t_addr addr, t_mem val)
  425. {
  426. class cl_mem *m;
  427. if ((m= (class cl_mem*)mems->at(type)))
  428. {
  429. m->write(addr, &val);
  430. //m->mem[addr]= val;
  431. }
  432. //FIXME
  433. else printf("cl_uc::write_mem(type= %d, 0x%06lx, 0x%lx) TROUBLE\n", type, addr, val);
  434. }
  435. void
  436. cl_uc::set_mem(enum mem_class type, t_addr addr, t_mem val)
  437. {
  438. class cl_mem *m;
  439. if ((m= (class cl_mem*)mems->at(type)))
  440. m->set(addr, val);
  441. //FIXME
  442. else printf("cl_uc::set_mem(type= %d, 0x%06lx, 0x%lx) TROUBLE\n", type, addr, val);
  443. }
  444. class cl_mem *
  445. cl_uc::mem(enum mem_class type)
  446. {
  447. if (mems->count < type)
  448. //FIXME
  449. {printf("TROUBLE\n"); return(0);
  450. }
  451. return((class cl_mem *)(mems->at(type)));
  452. }
  453. class cl_mem *
  454. cl_uc::mem(char *class_name)
  455. {
  456. int i, found= 0;
  457. char *mcn, *n, *s;
  458. if (!class_name)
  459. return(0);
  460. s= n= strdup(class_name);
  461. while (*s)
  462. {
  463. *s= toupper(*s);
  464. s++;
  465. }
  466. if (!class_name ||
  467. !(*class_name))
  468. return(0);
  469. for (i= 0; !found && i < mems->count; i++)
  470. {
  471. cl_mem *m= (cl_mem *)(mems->at(i));
  472. if (!m ||
  473. !m->class_name ||
  474. !(*(m->class_name)))
  475. continue;
  476. s= mcn= strdup(m->class_name);
  477. while (*s)
  478. {
  479. *s= toupper(*s);
  480. s++;
  481. }
  482. if (strstr(/*m->class_name*/mcn,/*class_name*/n) == /*m->class_name*/mcn)
  483. found= 1;
  484. free(mcn);
  485. if (found)
  486. {
  487. free(n);
  488. return(m);
  489. }
  490. }
  491. free(n);
  492. return(0);
  493. }
  494. /*TYPE_UBYTE *
  495. cl_uc::MEM(enum mem_class type)
  496. {
  497. class cl_mem *m;
  498. if ((m= mem(type)) == 0)
  499. //FIXME
  500. {printf("TROUBLE\n"); return(0);
  501. }
  502. return((TYPE_UBYTE *)(m->mem));
  503. }*/
  504. /* Local function for `read_hex_file' method to read some bytes */
  505. static long
  506. ReadInt(FILE *f, bool *ok, int bytes)
  507. {
  508. char s2[3];
  509. long l= 0;
  510. *ok= DD_FALSE;
  511. while (bytes)
  512. {
  513. if (fscanf(f, "%2c", &s2[0]) == EOF)
  514. return(0);
  515. s2[2]= '\0';
  516. l= l*256 + strtol(s2, NULL, 16);
  517. bytes--;
  518. }
  519. *ok= DD_TRUE;
  520. return(l);
  521. }
  522. /*
  523. * Reading intel hexa file into EROM
  524. *____________________________________________________________________________
  525. *
  526. * If parameter is a NULL pointer, this function reads data from `cmd_in'
  527. *
  528. */
  529. long
  530. cl_uc::read_hex_file(const char *name)
  531. {
  532. FILE *f;
  533. int c;
  534. long written= 0, recnum= 0;
  535. uchar dnum; // data number
  536. uchar rtyp=0; // record type
  537. uint addr= 0; // address
  538. uchar rec[300]; // data record
  539. uchar sum ; // checksum
  540. uchar chk ; // check
  541. int i;
  542. bool ok, get_low= 1;
  543. uchar low= 0, high;
  544. if (!name)
  545. {
  546. sim->app->get_commander()->
  547. printf("cl_uc::read_hex_file File name not specified\n");
  548. return(-1);
  549. }
  550. else
  551. if ((f= fopen(name, "r")) == NULL)
  552. {
  553. fprintf(stderr, "Can't open `%s': %s\n", name, strerror(errno));
  554. return(-1);
  555. }
  556. //memset(inst_map, '\0', sizeof(inst_map));
  557. ok= DD_TRUE;
  558. while (ok &&
  559. rtyp != 1)
  560. {
  561. while (((c= getc(f)) != ':') &&
  562. (c != EOF)) ;
  563. if (c != ':')
  564. {fprintf(stderr, ": not found\n");break;}
  565. recnum++;
  566. dnum= ReadInt(f, &ok, 1);//printf("dnum=%02x",dnum);
  567. chk = dnum;
  568. addr= ReadInt(f, &ok, 2);//printf("addr=%04x",addr);
  569. chk+= (addr & 0xff);
  570. chk+= ((addr >> 8) & 0xff);
  571. rtyp= ReadInt(f, &ok, 1);//printf("rtyp=%02x ",rtyp);
  572. chk+= rtyp;
  573. for (i= 0; ok && (i < dnum); i++)
  574. {
  575. rec[i]= ReadInt(f, &ok, 1);//printf("%02x",rec[i]);
  576. chk+= rec[i];
  577. }
  578. if (ok)
  579. {
  580. sum= ReadInt(f, &ok, 1);//printf(" sum=%02x\n",sum);
  581. if (ok)
  582. {
  583. if (((sum + chk) & 0xff) == 0)
  584. {
  585. if (rtyp == 0)
  586. {
  587. if (get_mem_width(MEM_ROM) > 8)
  588. addr/= 2;
  589. for (i= 0; i < dnum; i++)
  590. {
  591. if (get_mem_width(MEM_ROM) <= 8)
  592. {
  593. set_mem(MEM_ROM, addr, rec[i]);
  594. addr++;
  595. written++;
  596. }
  597. else if (get_mem_width(MEM_ROM) <= 16)
  598. {
  599. if (get_low)
  600. {
  601. low= rec[i];
  602. get_low= 0;
  603. }
  604. else
  605. {
  606. high= rec[i];
  607. set_mem(MEM_ROM, addr, (high*256)+low);
  608. addr++;
  609. written++;
  610. get_low= 1;
  611. }
  612. }
  613. }
  614. }
  615. else
  616. if (sim->app->args->get_iarg('V', 0) &&
  617. rtyp != 1)
  618. sim->app->get_commander()->
  619. printf("Unknown record type %d(0x%x)\n", rtyp, rtyp);
  620. }
  621. else
  622. if (sim->app->args->get_iarg('V', 0))
  623. sim->app->get_commander()->
  624. printf("Checksum error (%x instead of %x) in "
  625. "record %ld.\n", chk, sum, recnum);
  626. }
  627. else
  628. if (sim->app->args->get_iarg('V', 0))
  629. sim->app->get_commander()->
  630. printf("Read error in record %ld.\n", recnum);
  631. }
  632. }
  633. if (get_mem_width(MEM_ROM) > 8 &&
  634. !get_low)
  635. set_mem(MEM_ROM, addr, low);
  636. if (name)
  637. fclose(f);
  638. if (sim->app->args->get_iarg('V', 0))
  639. sim->app->get_commander()->printf("%ld records have been read\n", recnum);
  640. analyze(0);
  641. return(written);
  642. }
  643. /*
  644. * Handling instruction map
  645. *
  646. * `inst_at' is checking if the specified address is in instruction
  647. * map and `set_inst_at' marks the address in the map and
  648. * `del_inst_at' deletes the mark. `there_is_inst' cheks if there is
  649. * any mark in the map
  650. */
  651. bool
  652. cl_uc::inst_at(t_addr addr)
  653. {
  654. class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
  655. if (!rom)
  656. return(0);
  657. return(rom->inst_map->get(addr));
  658. }
  659. void
  660. cl_uc::set_inst_at(t_addr addr)
  661. {
  662. class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
  663. if (rom)
  664. rom->inst_map->set(addr);
  665. }
  666. void
  667. cl_uc::del_inst_at(t_addr addr)
  668. {
  669. class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
  670. if (rom)
  671. rom->inst_map->clear(addr);
  672. }
  673. bool
  674. cl_uc::there_is_inst(void)
  675. {
  676. class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
  677. if (!rom)
  678. return(0);
  679. return(!(rom->inst_map->empty()));
  680. }
  681. /*
  682. * Manipulating HW elements of the CPU
  683. *****************************************************************************
  684. */
  685. /* Register callback hw objects for mem read/write */
  686. void
  687. cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
  688. {
  689. class cl_mem *m;
  690. class cl_memloc *l;
  691. if ((m= (class cl_mem*)mems->at(type)))
  692. {
  693. if ((l= m->read_locs->get_loc(addr)) == 0)
  694. {
  695. l= new cl_memloc(addr);
  696. l->init();
  697. m->read_locs->add(l);
  698. }
  699. l->hws->add(hw);
  700. }
  701. else
  702. printf("cl_uc::register_hw_read TROUBLE\n");
  703. }
  704. void
  705. cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
  706. {
  707. }
  708. /* Looking for a specific HW element */
  709. class cl_hw *
  710. cl_uc::get_hw(enum hw_cath cath, int *idx)
  711. {
  712. class cl_hw *hw= 0;
  713. int i= 0;
  714. if (idx)
  715. i= *idx;
  716. for (; i < hws->count; i++)
  717. {
  718. hw= (class cl_hw *)(hws->at(i));
  719. if (hw->cathegory == cath)
  720. break;
  721. }
  722. if (i >= hws->count)
  723. return(0);
  724. if (idx)
  725. *idx= i;
  726. return(hw);
  727. }
  728. class cl_hw *
  729. cl_uc::get_hw(char *id_string, int *idx)
  730. {
  731. class cl_hw *hw= 0;
  732. int i= 0;
  733. if (idx)
  734. i= *idx;
  735. for (; i < hws->count; i++)
  736. {
  737. hw= (class cl_hw *)(hws->at(i));
  738. if (strstr(hw->id_string, id_string) == hw->id_string)
  739. break;
  740. }
  741. if (i >= hws->count)
  742. return(0);
  743. if (idx)
  744. *idx= i;
  745. return(hw);
  746. }
  747. class cl_hw *
  748. cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
  749. {
  750. class cl_hw *hw;
  751. int i= 0;
  752. if (idx)
  753. i= *idx;
  754. hw= get_hw(cath, &i);
  755. while (hw &&
  756. hw->id != hwid)
  757. {
  758. i++;
  759. hw= get_hw(cath, &i);
  760. }
  761. if (hw &&
  762. idx)
  763. *idx= i;
  764. return(hw);
  765. }
  766. class cl_hw *
  767. cl_uc::get_hw(char *id_string, int hwid, int *idx)
  768. {
  769. class cl_hw *hw;
  770. int i= 0;
  771. if (idx)
  772. i= *idx;
  773. hw= get_hw(id_string, &i);
  774. while (hw &&
  775. hw->id != hwid)
  776. {
  777. i++;
  778. hw= get_hw(id_string, &i);
  779. }
  780. if (hw &&
  781. idx)
  782. *idx= i;
  783. return(hw);
  784. }
  785. /*
  786. * Help of the command interpreter
  787. */
  788. struct dis_entry *
  789. cl_uc::dis_tbl(void)
  790. {
  791. static struct dis_entry empty= { 0, 0, 0, 0, NULL };
  792. return(&empty);
  793. }
  794. struct name_entry *
  795. cl_uc::sfr_tbl(void)
  796. {
  797. static struct name_entry empty= { 0, 0 };
  798. return(&empty);
  799. }
  800. struct name_entry *
  801. cl_uc::bit_tbl(void)
  802. {
  803. static struct name_entry empty= { 0, 0 };
  804. return(&empty);
  805. }
  806. char *
  807. cl_uc::disass(t_addr addr, char *sep)
  808. {
  809. char *buf;
  810. buf= (char*)malloc(100);
  811. strcpy(buf, "uc::do_disass unimplemented\n");
  812. return(buf);
  813. }
  814. void
  815. cl_uc::print_disass(t_addr addr, class cl_console *con)
  816. {
  817. char *dis;
  818. class cl_brk *b;
  819. int i;
  820. class cl_mem *rom= mem(MEM_ROM);
  821. t_mem code= get_mem(MEM_ROM, addr);
  822. if (!rom)
  823. return;
  824. b= fbrk_at(addr);
  825. dis= disass(addr, NULL);
  826. if (b)
  827. con->printf("%c", (b->perm == brkFIX)?'F':'D');
  828. else
  829. con->printf(" ");
  830. con->printf("%c ", inst_at(addr)?' ':'?');
  831. con->printf(rom->addr_format, addr); con->printf(" ");
  832. con->printf(rom->data_format, code);
  833. for (i= 1; i < inst_length(code); i++)
  834. {
  835. con->printf(" ");
  836. con->printf(rom->data_format, get_mem(MEM_ROM, addr+i));
  837. }
  838. int li= longest_inst();
  839. while (i < li)
  840. {
  841. int j;
  842. j= rom->width/4 + ((rom->width%4)?1:0) + 1;
  843. while (j)
  844. con->printf(" "), j--;
  845. i++;
  846. }
  847. con->printf(" %s\n", dis);
  848. free(dis);
  849. }
  850. void
  851. cl_uc::print_regs(class cl_console *con)
  852. {
  853. con->printf("No registers\n");
  854. }
  855. int
  856. cl_uc::inst_length(t_mem code)
  857. {
  858. struct dis_entry *tabl= dis_tbl();
  859. int i;
  860. for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++) ;
  861. return(tabl[i].mnemonic?tabl[i].length:1);
  862. }
  863. int
  864. cl_uc::longest_inst(void)
  865. {
  866. struct dis_entry *de= dis_tbl();
  867. int max= 0;
  868. while (de &&
  869. de->mnemonic)
  870. {
  871. if (de->length > max)
  872. max= de->length;
  873. de++;
  874. }
  875. return(max);
  876. }
  877. bool
  878. cl_uc::get_name(t_addr addr, struct name_entry tab[], char *buf)
  879. {
  880. int i;
  881. i= 0;
  882. while (tab[i].name &&
  883. (!(tab[i].cpu_type & type) ||
  884. (tab[i].addr != addr)))
  885. i++;
  886. if (tab[i].name)
  887. strcpy(buf, tab[i].name);
  888. return(tab[i].name != NULL);
  889. }
  890. char *
  891. cl_uc::symbolic_bit_name(t_addr bit_address,
  892. class cl_mem *mem,
  893. t_addr mem_addr,
  894. t_mem bit_mask)
  895. {
  896. char *sym_name= 0;
  897. int i;
  898. i= 0;
  899. while (bit_tbl()[i].name &&
  900. (bit_tbl()[i].addr != bit_address))
  901. i++;
  902. if (bit_tbl()[i].name)
  903. {
  904. sym_name= strdup(bit_tbl()[i].name);
  905. return(sym_name);
  906. }
  907. if (mem &&
  908. mem->class_name &&
  909. strstr(mem->class_name, "sfr") == mem->class_name)
  910. {
  911. i= 0;
  912. while (sfr_tbl()[i].name &&
  913. (sfr_tbl()[i].addr != mem_addr))
  914. i++;
  915. if (sfr_tbl()[i].name)
  916. sym_name= strdup(sfr_tbl()[i].name);
  917. else
  918. sym_name= 0;
  919. }
  920. if (!sym_name)
  921. {
  922. sym_name= (char *)malloc(16);
  923. sprintf(sym_name, mem?(mem->addr_format):"0x%06x", mem_addr);
  924. }
  925. sym_name= (char *)realloc(sym_name, strlen(sym_name)+2);
  926. strcat(sym_name, ".");
  927. i= 0;
  928. while (bit_mask > 1)
  929. {
  930. bit_mask>>=1;
  931. i++;
  932. }
  933. char bitnumstr[10];
  934. sprintf(bitnumstr, "%1d", i);
  935. strcat(sym_name, bitnumstr);
  936. return(sym_name);
  937. }
  938. /*
  939. * Execution
  940. */
  941. int
  942. cl_uc::tick(int cycles)
  943. {
  944. class cl_hw *hw;
  945. int i, cpc= clock_per_cycle();
  946. // increase time
  947. ticks->tick(cycles * cpc);
  948. class it_level *il= (class it_level *)(it_levels->top());
  949. if (il->level >= 0)
  950. isr_ticks->tick(cycles * cpc);
  951. if (state == stIDLE)
  952. idle_ticks->tick(cycles * cpc);
  953. for (i= 0; i < counters->count; i++)
  954. {
  955. class cl_ticker *t= (class cl_ticker *)(counters->at(i));
  956. if (t)
  957. {
  958. if ((t->options&TICK_INISR) ||
  959. il->level < 0)
  960. t->tick(cycles * cpc);
  961. }
  962. }
  963. // tick hws
  964. for (i= 0; i < hws->count; i++)
  965. {
  966. hw= (class cl_hw *)(hws->at(i));
  967. if (hw->flags & HWF_INSIDE)
  968. hw->tick(cycles);
  969. }
  970. return(0);
  971. }
  972. class cl_ticker *
  973. cl_uc::get_counter(int nr)
  974. {
  975. if (nr >= counters->count)
  976. return(0);
  977. return((class cl_ticker *)(counters->at(nr)));
  978. }
  979. class cl_ticker *
  980. cl_uc::get_counter(char *name)
  981. {
  982. int i;
  983. if (!name)
  984. return(0);
  985. for (i= 0; i < counters->count; i++)
  986. {
  987. class cl_ticker *t= (class cl_ticker *)(counters->at(i));
  988. if (t &&
  989. t->name &&
  990. strcmp(t->name, name) == 0)
  991. return(t);
  992. }
  993. return(0);
  994. }
  995. void
  996. cl_uc::add_counter(class cl_ticker *ticker, int nr)
  997. {
  998. while (counters->count <= nr)
  999. counters->add(0);
  1000. counters->put_at(nr, ticker);
  1001. }
  1002. void
  1003. cl_uc::add_counter(class cl_ticker *ticker, char */*name*/)
  1004. {
  1005. int i;
  1006. if (counters->count < 1)
  1007. counters->add(0);
  1008. for (i= 1; i < counters->count; i++)
  1009. {
  1010. class cl_ticker *t= (class cl_ticker *)(counters->at(i));
  1011. if (!t)
  1012. {
  1013. counters->put_at(i, ticker);
  1014. return;
  1015. }
  1016. }
  1017. counters->add(ticker);
  1018. }
  1019. void
  1020. cl_uc::del_counter(int nr)
  1021. {
  1022. class cl_ticker *t;
  1023. if (nr >= counters->count)
  1024. return;
  1025. if ((t= (class cl_ticker *)(counters->at(0))) != 0)
  1026. delete t;
  1027. counters->put_at(nr, 0);
  1028. }
  1029. void
  1030. cl_uc::del_counter(char *name)
  1031. {
  1032. int i;
  1033. if (!name)
  1034. return;
  1035. for (i= 0; i < counters->count; i++)
  1036. {
  1037. class cl_ticker *t= (class cl_ticker *)(counters->at(i));
  1038. if (t &&
  1039. t->name &&
  1040. strcmp(t->name, name) == 0)
  1041. {
  1042. delete t;
  1043. counters->put_at(i, 0);
  1044. return;
  1045. }
  1046. }
  1047. }
  1048. /*
  1049. * Fetch without checking for breakpoint hit
  1050. */
  1051. t_mem
  1052. cl_uc::fetch(void)
  1053. {
  1054. ulong code;
  1055. code= read_mem(MEM_ROM, PC);
  1056. PC++;
  1057. if (PC >= get_mem_size(MEM_ROM))
  1058. PC= 0;
  1059. return(code);
  1060. }
  1061. /*
  1062. * Fetch but checking for breakpoint hit first
  1063. */
  1064. bool
  1065. cl_uc::fetch(t_mem *code)
  1066. {
  1067. class cl_brk *brk;
  1068. int idx;
  1069. if (!code)
  1070. return(0);
  1071. if (sim->state & SIM_GO)
  1072. {
  1073. if ((brk= fbrk->get_bp(PC, &idx)) &&
  1074. (brk->do_hit()))
  1075. {
  1076. if (brk->perm == brkDYNAMIC)
  1077. fbrk->del_bp(PC);
  1078. return(1);
  1079. }
  1080. }
  1081. *code= fetch();
  1082. return(0);
  1083. }
  1084. int
  1085. cl_uc::do_inst(int step)
  1086. {
  1087. int res= resGO;
  1088. if (step < 0)
  1089. step= 1;
  1090. while (step-- &&
  1091. res == resGO)
  1092. {
  1093. pre_inst();
  1094. res= exec_inst();
  1095. post_inst();
  1096. }
  1097. if (res != resGO)
  1098. sim->stop(res);
  1099. return(res);
  1100. }
  1101. void
  1102. cl_uc::pre_inst(void)
  1103. {}
  1104. int
  1105. cl_uc::exec_inst(void)
  1106. {
  1107. return(resGO);
  1108. }
  1109. void
  1110. cl_uc::post_inst(void)
  1111. {}
  1112. /*
  1113. * Time related functions
  1114. */
  1115. double
  1116. cl_uc::get_rtime(void)
  1117. {
  1118. /* double d;
  1119. d= (double)ticks/xtal;
  1120. return(d);*/
  1121. return(ticks->get_rtime(xtal));
  1122. }
  1123. int
  1124. cl_uc::clock_per_cycle(void)
  1125. {
  1126. return(1);
  1127. }
  1128. /*
  1129. * Stack tracking system
  1130. */
  1131. void
  1132. cl_uc::st_push(class cl_stack_op *op)
  1133. {
  1134. st_ops->push(op);
  1135. }
  1136. void
  1137. cl_uc::st_call(class cl_stack_op *op)
  1138. {
  1139. st_ops->push(op);
  1140. }
  1141. int
  1142. cl_uc::st_pop(class cl_stack_op *op)
  1143. {
  1144. class cl_stack_op *sop= (class cl_stack_op *)(st_ops->pop());
  1145. if (!sop)
  1146. return(1);
  1147. return(0);
  1148. }
  1149. int
  1150. cl_uc::st_ret(class cl_stack_op *op)
  1151. {
  1152. class cl_stack_op *sop= (class cl_stack_op *)(st_ops->pop());
  1153. if (!sop)
  1154. return(1);
  1155. return(0);
  1156. }
  1157. /*
  1158. * Breakpoint handling
  1159. */
  1160. class cl_fetch_brk *
  1161. cl_uc::fbrk_at(t_addr addr)
  1162. {
  1163. int idx;
  1164. return((class cl_fetch_brk *)(fbrk->get_bp(addr, &idx)));
  1165. }
  1166. class cl_ev_brk *
  1167. cl_uc::ebrk_at(t_addr addr, char *id)
  1168. {
  1169. int i;
  1170. class cl_ev_brk *eb;
  1171. for (i= 0; i < ebrk->count; i++)
  1172. {
  1173. eb= (class cl_ev_brk *)(ebrk->at(i));
  1174. if (eb->addr == addr &&
  1175. !strcmp(eb->id, id))
  1176. return(eb);
  1177. }
  1178. return(0);
  1179. }
  1180. /*void
  1181. cl_uc::rm_fbrk(long addr)
  1182. {
  1183. fbrk->del_bp(addr);
  1184. }*/
  1185. /* Get a breakpoint specified by its number */
  1186. class cl_brk *
  1187. cl_uc::brk_by_nr(int nr)
  1188. {
  1189. class cl_brk *bp;
  1190. if ((bp= fbrk->get_bp(nr)))
  1191. return(bp);
  1192. if ((bp= ebrk->get_bp(nr)))
  1193. return(bp);
  1194. return(0);
  1195. }
  1196. /* Get a breakpoint from the specified collection by its number */
  1197. class cl_brk *
  1198. cl_uc::brk_by_nr(class brk_coll *bpcoll, int nr)
  1199. {
  1200. class cl_brk *bp;
  1201. if ((bp= bpcoll->get_bp(nr)))
  1202. return(bp);
  1203. return(0);
  1204. }
  1205. /* Remove an event breakpoint specified by its address and id */
  1206. void
  1207. cl_uc::rm_ebrk(t_addr addr, char *id)
  1208. {
  1209. int i;
  1210. class cl_ev_brk *eb;
  1211. for (i= 0; i < ebrk->count; i++)
  1212. {
  1213. eb= (class cl_ev_brk *)(ebrk->at(i));
  1214. if (eb->addr == addr &&
  1215. !strcmp(eb->id, id))
  1216. ebrk->free_at(i);
  1217. }
  1218. }
  1219. /* Remove a breakpoint specified by its number */
  1220. void
  1221. cl_uc::rm_brk(int nr)
  1222. {
  1223. class cl_brk *bp;
  1224. if ((bp= brk_by_nr(fbrk, nr)))
  1225. fbrk->del_bp(bp->addr);
  1226. else if ((bp= brk_by_nr(ebrk, nr)))
  1227. ebrk->free_at(ebrk->index_of(bp));
  1228. }
  1229. void
  1230. cl_uc::put_breaks(void)
  1231. {}
  1232. /* Remove all fetch and event breakpoints */
  1233. void
  1234. cl_uc::remove_all_breaks(void)
  1235. {
  1236. while (fbrk->count)
  1237. {
  1238. class cl_brk *brk= (class cl_brk *)(fbrk->at(0));
  1239. fbrk->del_bp(brk->addr);
  1240. }
  1241. while (ebrk->count)
  1242. ebrk->free_at(ebrk->count-1);
  1243. }
  1244. int
  1245. cl_uc::make_new_brknr(void)
  1246. {
  1247. if (brk_counter == 0)
  1248. return(brk_counter= 1);
  1249. if (fbrk->count == 0 &&
  1250. ebrk->count == 0)
  1251. return(brk_counter= 1);
  1252. return(++brk_counter);
  1253. }
  1254. class cl_ev_brk *
  1255. cl_uc::mk_ebrk(enum brk_perm perm, class cl_mem *mem,
  1256. char op, t_addr addr, int hit)
  1257. {
  1258. class cl_ev_brk *b;
  1259. op= toupper(op);
  1260. switch (mem->type)
  1261. {
  1262. case MEM_ROM:
  1263. if (op == 'R')
  1264. b= new cl_rc_brk(make_new_brknr(), addr, perm, hit);
  1265. else
  1266. return(0);
  1267. break;
  1268. case MEM_IRAM:
  1269. if (op == 'R')
  1270. b= new cl_ri_brk(make_new_brknr(), addr, perm, hit);
  1271. else if (op == 'W')
  1272. b= new cl_wi_brk(make_new_brknr(), addr, perm, hit);
  1273. else
  1274. return(0);
  1275. break;
  1276. case MEM_XRAM:
  1277. if (op == 'R')
  1278. b= new cl_rx_brk(make_new_brknr(), addr, perm, hit);
  1279. else if (op == 'W')
  1280. b= new cl_wx_brk(make_new_brknr(), addr, perm, hit);
  1281. else
  1282. return(0);
  1283. break;
  1284. case MEM_SFR:
  1285. if (op == 'R')
  1286. b= new cl_rs_brk(make_new_brknr(), addr, perm, hit);
  1287. else if (op == 'W')
  1288. b= new cl_ws_brk(make_new_brknr(), addr, perm, hit);
  1289. else
  1290. return(0);
  1291. break;
  1292. default:
  1293. return(0);
  1294. }
  1295. b->init();
  1296. return(b);
  1297. }
  1298. /* End of uc.cc */