PageRenderTime 53ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 1ms

/branches/gbdk-297/sdcc/sim/ucsim/sim.src/uc.cc

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