PageRenderTime 63ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/sdcc-310/sim/ucsim/z80.src/r2k.cc

#
C++ | 646 lines | 456 code | 98 blank | 92 comment | 65 complexity | dcd8c7e6bf6eef9dfa3c17a654341f1b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, GPL-3.0
  1. /*
  2. * Simulator of microcontrollers (r2k.cc)
  3. *
  4. * Derived from ucSim z80.src/z80.cc
  5. * Modified for rabbit 2000 by Leland Morrison 2011
  6. *
  7. * some z80 code base from Karl Bongers karl@turbobit.com
  8. *
  9. * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
  10. *
  11. * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
  12. *
  13. */
  14. /* This file is part of microcontroller simulator: ucsim.
  15. UCSIM is free software; you can redistribute it and/or modify
  16. it under the terms of the GNU General Public License as published by
  17. the Free Software Foundation; either version 2 of the License, or
  18. (at your option) any later version.
  19. UCSIM is distributed in the hope that it will be useful,
  20. but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. GNU General Public License for more details.
  23. You should have received a copy of the GNU General Public License
  24. along with UCSIM; see the file COPYING. If not, write to the Free
  25. Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  26. 02111-1307, USA. */
  27. /*@1@*/
  28. #include "ddconfig.h"
  29. #include <stdarg.h> /* for va_list */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <ctype.h>
  33. #include "i_string.h"
  34. // prj
  35. #include "pobjcl.h"
  36. // sim
  37. #include "simcl.h"
  38. // local
  39. #include "z80cl.h"
  40. #include "r2kcl.h"
  41. #include "glob.h"
  42. #define uint32 t_addr
  43. #define uint8 unsigned char
  44. /*******************************************************************/
  45. /*
  46. * Rabbit 2000 micro-controller object
  47. * (base for Rabbit 3000/4000/5000)
  48. */
  49. cl_r2k::cl_r2k(int Itype, int Itech, class cl_sim *asim):
  50. cl_z80(Itype, Itech, asim), mmu(this)
  51. {
  52. type= Itype;
  53. }
  54. int
  55. cl_r2k::init(void)
  56. {
  57. cl_uc::init(); /* Memories now exist */
  58. rom= address_space(MEM_ROM_ID);
  59. // ram= mem(MEM_XRAM);
  60. ram= rom;
  61. // zero out ram(this is assumed in regression tests)
  62. for (int i=0x8000; i<0x10000; i++) {
  63. ram->set((t_addr) i, 0);
  64. }
  65. return(0);
  66. }
  67. const char *
  68. cl_r2k::id_string(void)
  69. {
  70. return("rabbit 2000");
  71. }
  72. /*
  73. * Making elements of the controller
  74. */
  75. /*
  76. t_addr
  77. cl_r2k::get_mem_size(enum mem_class type)
  78. {
  79. switch(type)
  80. {
  81. case MEM_ROM: return(0x10000);
  82. case MEM_XRAM: return(0x10000);
  83. default: return(0);
  84. }
  85. return(cl_uc::get_mem_size(type));
  86. }
  87. */
  88. void
  89. cl_r2k::mk_hw_elements(void)
  90. {
  91. //class cl_base *o;
  92. /* t_uc::mk_hw() does nothing */
  93. }
  94. void
  95. cl_r2k::make_memories(void)
  96. {
  97. class cl_address_space *as;
  98. as= new cl_address_space("rom", 0, 0x10000, 8);
  99. as->init();
  100. address_spaces->add(as);
  101. class cl_address_decoder *ad;
  102. class cl_memory_chip *chip;
  103. chip= new cl_memory_chip("rom_chip", 0x10000, 8);
  104. chip->init();
  105. memchips->add(chip);
  106. ad= new cl_address_decoder(as= address_space("rom"), chip, 0, 0xffff, 0);
  107. ad->init();
  108. as->decoders->add(ad);
  109. ad->activate(0);
  110. }
  111. /*
  112. * Help command interpreter
  113. */
  114. struct dis_entry *
  115. cl_r2k::dis_tbl(void)
  116. {
  117. return(disass_r2k);
  118. }
  119. /*struct name_entry *
  120. cl_r2k::sfr_tbl(void)
  121. {
  122. return(0);
  123. }*/
  124. /*struct name_entry *
  125. cl_r2k::bit_tbl(void)
  126. {
  127. //FIXME
  128. return(0);
  129. }*/
  130. int
  131. cl_r2k::inst_length(t_addr addr)
  132. {
  133. int len = 0;
  134. get_disasm_info(addr, &len, NULL, NULL);
  135. return len;
  136. }
  137. int
  138. cl_r2k::inst_branch(t_addr addr)
  139. {
  140. int b;
  141. get_disasm_info(addr, NULL, &b, NULL);
  142. return b;
  143. }
  144. int
  145. cl_r2k::longest_inst(void)
  146. {
  147. return 4;
  148. }
  149. const char *
  150. cl_r2k::get_disasm_info(t_addr addr,
  151. int *ret_len,
  152. int *ret_branch,
  153. int *immed_offset)
  154. {
  155. const char *b = NULL;
  156. uint code;
  157. int len = 0;
  158. int immed_n = 0;
  159. int i;
  160. int start_addr = addr;
  161. struct dis_entry *dis_e;
  162. code= get_mem(MEM_ROM_ID, addr++);
  163. dis_e = NULL;
  164. switch(code) {
  165. case 0xcb: /* ESC code to lots of op-codes, all 2-byte */
  166. code= get_mem(MEM_ROM_ID, addr++);
  167. i= 0;
  168. while ((code & disass_r2k_cb[i].mask) != disass_r2k_cb[i].code &&
  169. disass_r2k_cb[i].mnemonic)
  170. i++;
  171. dis_e = &disass_r2k_cb[i];
  172. b= disass_r2k_cb[i].mnemonic;
  173. if (b != NULL)
  174. len += (disass_r2k_cb[i].length + 1);
  175. break;
  176. case 0xed: /* ESC code to about 80 opcodes of various lengths */
  177. code= get_mem(MEM_ROM_ID, addr++);
  178. i= 0;
  179. while ((code & disass_r2k_ed[i].mask) != disass_r2k_ed[i].code &&
  180. disass_r2k_ed[i].mnemonic)
  181. i++;
  182. dis_e = &disass_r2k_ed[i];
  183. b= disass_r2k_ed[i].mnemonic;
  184. if (b != NULL)
  185. len += (disass_r2k_ed[i].length + 1);
  186. break;
  187. case 0xdd: /* ESC codes,about 284, vary lengths, IX centric */
  188. code= get_mem(MEM_ROM_ID, addr++);
  189. if (code == 0xcb) {
  190. immed_n = 2;
  191. addr++; // pass up immed data
  192. code= get_mem(MEM_ROM_ID, addr++);
  193. i= 0;
  194. while ((code & disass_r2k_ddcb[i].mask) != disass_r2k_ddcb[i].code &&
  195. disass_r2k_ddcb[i].mnemonic)
  196. i++;
  197. dis_e = &disass_r2k_ddcb[i];
  198. b= disass_r2k_ddcb[i].mnemonic;
  199. if (b != NULL)
  200. len += (disass_r2k_ddcb[i].length + 2);
  201. } else {
  202. i= 0;
  203. while ((code & disass_r2k_dd[i].mask) != disass_r2k_dd[i].code &&
  204. disass_r2k_dd[i].mnemonic)
  205. i++;
  206. dis_e = &disass_r2k_dd[i];
  207. b= disass_r2k_dd[i].mnemonic;
  208. if (b != NULL)
  209. len += (disass_r2k_dd[i].length + 1);
  210. }
  211. break;
  212. case 0xfd: /* ESC codes,sme as dd but IY centric */
  213. code= get_mem(MEM_ROM_ID, addr++);
  214. if (code == 0xcb) {
  215. immed_n = 2;
  216. addr++; // pass up immed data
  217. code= get_mem(MEM_ROM_ID, addr++);
  218. i= 0;
  219. while ((code & disass_r2k_fdcb[i].mask) != disass_r2k_fdcb[i].code &&
  220. disass_r2k_fdcb[i].mnemonic)
  221. i++;
  222. dis_e = &disass_r2k_fdcb[i];
  223. b= disass_r2k_fdcb[i].mnemonic;
  224. if (b != NULL)
  225. len += (disass_r2k_fdcb[i].length + 2);
  226. } else {
  227. i= 0;
  228. while ((code & disass_r2k_fd[i].mask) != disass_r2k_fd[i].code &&
  229. disass_r2k_fd[i].mnemonic)
  230. i++;
  231. dis_e = &disass_r2k_fd[i];
  232. b= disass_r2k_fd[i].mnemonic;
  233. if (b != NULL)
  234. len += (disass_r2k_fd[i].length + 1);
  235. }
  236. break;
  237. default:
  238. i= 0;
  239. while ((code & disass_r2k[i].mask) != disass_r2k[i].code &&
  240. disass_r2k[i].mnemonic)
  241. i++;
  242. dis_e = &disass_r2k[i];
  243. b= disass_r2k[i].mnemonic;
  244. if (b != NULL)
  245. len += (disass_r2k[i].length);
  246. break;
  247. }
  248. if (ret_branch) {
  249. *ret_branch = dis_e->branch;
  250. }
  251. if (immed_offset) {
  252. if (immed_n > 0)
  253. *immed_offset = immed_n;
  254. else *immed_offset = (addr - start_addr);
  255. }
  256. if (len == 0)
  257. len = 1;
  258. if (ret_len)
  259. *ret_len = len;
  260. return b;
  261. }
  262. const char *
  263. cl_r2k::disass(t_addr addr, const char *sep)
  264. {
  265. char work[256], temp[20];
  266. const char *b;
  267. char *buf, *p, *t;
  268. int len = 0;
  269. int immed_offset = 0;
  270. p= work;
  271. b = get_disasm_info(addr, &len, NULL, &immed_offset);
  272. if (b == NULL) {
  273. buf= (char*)malloc(30);
  274. strcpy(buf, "UNKNOWN/INVALID");
  275. return(buf);
  276. }
  277. while (*b)
  278. {
  279. if (*b == '%')
  280. {
  281. b++;
  282. switch (*(b++))
  283. {
  284. case 'd': // d jump relative target, signed? byte immediate operand
  285. sprintf(temp, "#%d", (char)get_mem(MEM_ROM_ID, addr+immed_offset));
  286. ++immed_offset;
  287. break;
  288. case 'w': // w word immediate operand
  289. sprintf(temp, "#0x%04x",
  290. (uint)((get_mem(MEM_ROM_ID, addr+immed_offset)) |
  291. (get_mem(MEM_ROM_ID, addr+immed_offset+1)<<8)) );
  292. ++immed_offset;
  293. ++immed_offset;
  294. break;
  295. case 'b': // b byte immediate operand
  296. sprintf(temp, "#0x%02x", (uint)get_mem(MEM_ROM_ID, addr+immed_offset));
  297. ++immed_offset;
  298. break;
  299. default:
  300. strcpy(temp, "?");
  301. break;
  302. }
  303. t= temp;
  304. while (*t)
  305. *(p++)= *(t++);
  306. }
  307. else
  308. *(p++)= *(b++);
  309. }
  310. *p= '\0';
  311. p= strchr(work, ' ');
  312. if (!p)
  313. {
  314. buf= strdup(work);
  315. return(buf);
  316. }
  317. if (sep == NULL)
  318. buf= (char *)malloc(6+strlen(p)+1);
  319. else
  320. buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
  321. for (p= work, t= buf; *p != ' '; p++, t++)
  322. *t= *p;
  323. p++;
  324. *t= '\0';
  325. if (sep == NULL)
  326. {
  327. while (strlen(buf) < 6)
  328. strcat(buf, " ");
  329. }
  330. else
  331. strcat(buf, sep);
  332. strcat(buf, p);
  333. return(buf);
  334. }
  335. void
  336. cl_r2k::print_regs(class cl_console_base *con)
  337. {
  338. con->dd_printf("SZ-A-PNC Flags= 0x%02x %3d %c ",
  339. regs.F, regs.F, isprint(regs.F)?regs.F:'.');
  340. con->dd_printf("A= 0x%02x %3d %c\n",
  341. regs.A, regs.A, isprint(regs.A)?regs.A:'.');
  342. con->dd_printf("%c%c-%c-%c%c%c\n",
  343. (regs.F&BIT_S)?'1':'0',
  344. (regs.F&BIT_Z)?'1':'0',
  345. (regs.F&BIT_A)?'1':'0',
  346. (regs.F&BIT_P)?'1':'0',
  347. (regs.F&BIT_N)?'1':'0',
  348. (regs.F&BIT_C)?'1':'0');
  349. con->dd_printf("BC= 0x%04x [BC]= %02x %3d %c ",
  350. regs.BC, ram->get(regs.BC), ram->get(regs.BC),
  351. isprint(ram->get(regs.BC))?ram->get(regs.BC):'.');
  352. con->dd_printf("DE= 0x%04x [DE]= %02x %3d %c ",
  353. regs.DE, ram->get(regs.DE), ram->get(regs.DE),
  354. isprint(ram->get(regs.DE))?ram->get(regs.DE):'.');
  355. con->dd_printf("HL= 0x%04x [HL]= %02x %3d %c\n",
  356. regs.HL, ram->get(regs.HL), ram->get(regs.HL),
  357. isprint(ram->get(regs.HL))?ram->get(regs.HL):'.');
  358. con->dd_printf("IX= 0x%04x [IX]= %02x %3d %c ",
  359. regs.IX, ram->get(regs.IX), ram->get(regs.IX),
  360. isprint(ram->get(regs.IX))?ram->get(regs.IX):'.');
  361. con->dd_printf("IY= 0x%04x [IY]= %02x %3d %c ",
  362. regs.IY, ram->get(regs.IY), ram->get(regs.IY),
  363. isprint(ram->get(regs.IY))?ram->get(regs.IY):'.');
  364. con->dd_printf("SP= 0x%04x [SP]= %02x %3d %c\n",
  365. regs.SP, ram->get(regs.SP), ram->get(regs.SP),
  366. isprint(ram->get(regs.SP))?ram->get(regs.SP):'.');
  367. print_disass(PC, con);
  368. }
  369. /*
  370. * Execution
  371. */
  372. int
  373. cl_r2k::exec_inst(void)
  374. {
  375. t_mem code;
  376. if (fetch(&code))
  377. return(resBREAKPOINT);
  378. tick(1);
  379. /* handling for IOI and IOE prefixes */
  380. mmu.io_flag = 0;
  381. if ((code == 0xd3) || (code == 0xdb)) {
  382. mmu.io_flag = (code == 0xdb) ? IOI : IOE;
  383. if (fetch(&code))
  384. return(resBREAKPOINT);
  385. tick(1);
  386. }
  387. switch (code)
  388. {
  389. case 0x00: return(inst_nop(code));
  390. case 0x01: case 0x02: case 0x06: return(inst_ld(code));
  391. case 0x03: case 0x04: return(inst_inc(code));
  392. case 0x05: return(inst_dec(code));
  393. case 0x07: return(inst_rlca(code));
  394. case 0x08: return(inst_ex(code));
  395. case 0x09: return(inst_add(code));
  396. case 0x0a: case 0x0e: return(inst_ld(code));
  397. case 0x0b: case 0x0d: return(inst_dec(code));
  398. case 0x0c: return(inst_inc(code));
  399. case 0x0f: return(inst_rrca(code));
  400. case 0x10: return(inst_djnz(code));
  401. case 0x11: case 0x12: case 0x16: return(inst_ld(code));
  402. case 0x13: case 0x14: return(inst_inc(code));
  403. case 0x15: return(inst_dec(code));
  404. case 0x17: return(inst_rla(code));
  405. case 0x18: return(inst_jr(code));
  406. case 0x19: return(inst_add(code));
  407. case 0x1a: case 0x1e: return(inst_ld(code));
  408. case 0x1b: case 0x1d: return(inst_dec(code));
  409. case 0x1c: return(inst_inc(code));
  410. case 0x1f: return(inst_rra(code));
  411. case 0x20: return(inst_jr(code));
  412. case 0x21: case 0x22: case 0x26: return(inst_ld(code));
  413. case 0x23: case 0x24: return(inst_inc(code));
  414. case 0x25: return(inst_dec(code));
  415. //case 0x27: return(inst_daa(code));
  416. case 0x27: return(inst_add_sp_d(code));
  417. case 0x28: return(inst_jr(code));
  418. case 0x29: return(inst_add(code));
  419. case 0x2a: case 0x2e: return(inst_ld(code));
  420. case 0x2b: case 0x2d: return(inst_dec(code));
  421. case 0x2c: return(inst_inc(code));
  422. case 0x2f: return(inst_cpl(code));
  423. case 0x30: return(inst_jr(code));
  424. case 0x31: case 0x32: case 0x36: return(inst_ld(code));
  425. case 0x33: case 0x34: return(inst_inc(code));
  426. case 0x35: return(inst_dec(code));
  427. case 0x37: return(inst_scf(code));
  428. case 0x38: return(inst_jr(code));
  429. case 0x39: return(inst_add(code));
  430. case 0x3a: case 0x3e: return(inst_ld(code));
  431. case 0x3b: case 0x3d: return(inst_dec(code));
  432. case 0x3c: return(inst_inc(code));
  433. case 0x3f: return(inst_ccf(code));
  434. case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
  435. case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
  436. return(inst_ld(code));
  437. case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
  438. case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
  439. return(inst_ld(code));
  440. case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
  441. case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
  442. return(inst_ld(code));
  443. case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x77:
  444. case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
  445. return(inst_ld(code));
  446. case 0x76:
  447. //return(inst_halt(code));
  448. return(inst_altd(code));
  449. case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
  450. return(inst_add(code));
  451. case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
  452. return(inst_adc(code));
  453. case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
  454. return(inst_sub(code));
  455. case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
  456. return(inst_sbc(code));
  457. case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
  458. return(inst_and(code));
  459. case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
  460. return(inst_xor(code));
  461. case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
  462. return(inst_or(code));
  463. case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
  464. return(inst_cp(code));
  465. case 0xc0: return(inst_ret(code));
  466. case 0xc1: return(inst_pop(code));
  467. case 0xc2: case 0xc3: return(inst_jp(code));
  468. case 0xc4: return(inst_r2k_ld(code));
  469. case 0xc5: return(inst_push(code));
  470. case 0xc6: return(inst_add(code));
  471. case 0xc7: return(inst_ljp(code));
  472. case 0xc8: case 0xc9: return(inst_ret(code));
  473. case 0xca: return(inst_jp(code));
  474. /* CB escapes out to 2 byte opcodes(CB include), opcodes
  475. to do register bit manipulations */
  476. case 0xcb: return(inst_cb());
  477. case 0xcc: return(inst_bool(code));
  478. case 0xcd: return(inst_call(code));
  479. case 0xce: return(inst_adc(code));
  480. case 0xcf: return(inst_lcall(code));
  481. case 0xd0: return(inst_ret(code));
  482. case 0xd1: return(inst_pop(code));
  483. case 0xd2: return(inst_jp(code));
  484. case 0xd3: /* error (ioi prefix) */ break;
  485. case 0xd4: return(inst_r2k_ld(code));
  486. case 0xd5: return(inst_push(code));
  487. case 0xd6: return(inst_sub(code));
  488. case 0xd7: return(inst_rst(code));
  489. case 0xd8: return(inst_ret(code));
  490. case 0xd9: return(inst_exx(code));
  491. case 0xda: return(inst_jp(code));
  492. case 0xdb: /* error (ioe prefix) */ break;
  493. case 0xdc: return(inst_r2k_and(code));
  494. /* DD escapes out to 2 to 4 byte opcodes(DD included)
  495. with a variety of uses. It can precede the CB escape
  496. sequence to extend CB codes with IX+immed_byte */
  497. case 0xdd: return(inst_xd(code));
  498. case 0xde: return(inst_sbc(code));
  499. case 0xdf: return(inst_rst(code));
  500. case 0xe0: return(inst_ret(code));
  501. case 0xe1: return(inst_pop(code));
  502. case 0xe2: return(inst_jp(code));
  503. case 0xe3: return(inst_r2k_ex(code));
  504. case 0xe4: return(inst_r2k_ld(code));
  505. case 0xe5: return(inst_push(code));
  506. case 0xe6: return(inst_and(code));
  507. case 0xe7: return(inst_rst(code));
  508. case 0xe8: return(inst_ret(code));
  509. case 0xe9: return(inst_jp(code));
  510. case 0xea: return(inst_jp(code));
  511. case 0xeb: return(inst_ex(code));
  512. case 0xec: return(inst_r2k_or (code));
  513. /* ED escapes out to other oddball opcodes */
  514. case 0xed: return(inst_ed());
  515. case 0xee: return(inst_xor(code));
  516. case 0xef: return(inst_rst(code));
  517. case 0xf0: return(inst_ret(code));
  518. case 0xf1: return(inst_pop(code));
  519. case 0xf2: return(inst_jp(code));
  520. case 0xf3: return(inst_rl_de(code));
  521. case 0xf4: return(inst_r2k_ld(code));
  522. case 0xf5: return(inst_push(code));
  523. case 0xf6: return(inst_or(code));
  524. case 0xf7: return(inst_mul(code));
  525. case 0xf8: return(inst_ret(code));
  526. case 0xf9: return(inst_ld(code));
  527. case 0xfa: return(inst_jp(code));
  528. case 0xfb: return(inst_rr_de(code));
  529. case 0xfc: return(inst_rr_hl(code));
  530. /* FD escapes out to 2 to 4 byte opcodes(DD included)
  531. with a variety of uses. It can precede the CB escape
  532. sequence to extend CB codes with IX+immed_byte */
  533. case 0xfd: return(inst_xd(code));
  534. case 0xfe: return(inst_cp(code));
  535. case 0xff: return(inst_rst(code));
  536. }
  537. /*if (PC)
  538. PC--;
  539. else
  540. PC= get_mem_size(MEM_ROM_ID)-1;*/
  541. PC= rom->inc_address(PC, -1);
  542. sim->stop(resINV_INST);
  543. return(resINV_INST);
  544. }
  545. /* End of z80.src/z80.cc */