m68hc11_sim.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. /* m6811_cpu.c -- 68HC11&68HC12 CPU Emulation
  2. Copyright 1999-2015 Free Software Foundation, Inc.
  3. Written by Stephane Carrez (stcarrez@nerim.fr)
  4. This file is part of GDB, GAS, and the GNU binutils.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. #include "sim-main.h"
  16. #include "sim-assert.h"
  17. #include "sim-module.h"
  18. #include "sim-options.h"
  19. enum {
  20. OPTION_CPU_RESET = OPTION_START,
  21. OPTION_EMUL_OS,
  22. OPTION_CPU_CONFIG,
  23. OPTION_CPU_BOOTSTRAP,
  24. OPTION_CPU_MODE
  25. };
  26. static DECLARE_OPTION_HANDLER (cpu_option_handler);
  27. static const OPTION cpu_options[] =
  28. {
  29. { {"cpu-reset", no_argument, NULL, OPTION_CPU_RESET },
  30. '\0', NULL, "Reset the CPU",
  31. cpu_option_handler },
  32. { {"emulos", no_argument, NULL, OPTION_EMUL_OS },
  33. '\0', NULL, "Emulate some OS system calls (read, write, ...)",
  34. cpu_option_handler },
  35. { {"cpu-config", required_argument, NULL, OPTION_CPU_CONFIG },
  36. '\0', NULL, "Specify the initial CPU configuration register",
  37. cpu_option_handler },
  38. { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
  39. '\0', NULL, "Start the processing in bootstrap mode",
  40. cpu_option_handler },
  41. { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
  42. };
  43. static SIM_RC
  44. cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
  45. int opt, char *arg, int is_command)
  46. {
  47. int val;
  48. cpu = STATE_CPU (sd, 0);
  49. switch (opt)
  50. {
  51. case OPTION_CPU_RESET:
  52. sim_board_reset (sd);
  53. break;
  54. case OPTION_EMUL_OS:
  55. cpu->cpu_emul_syscall = 1;
  56. break;
  57. case OPTION_CPU_CONFIG:
  58. if (sscanf(arg, "0x%x", &val) == 1
  59. || sscanf(arg, "%d", &val) == 1)
  60. {
  61. cpu->cpu_config = val;
  62. cpu->cpu_use_local_config = 1;
  63. }
  64. else
  65. cpu->cpu_use_local_config = 0;
  66. break;
  67. case OPTION_CPU_BOOTSTRAP:
  68. cpu->cpu_start_mode = "bootstrap";
  69. break;
  70. case OPTION_CPU_MODE:
  71. break;
  72. }
  73. return SIM_RC_OK;
  74. }
  75. void
  76. cpu_call (sim_cpu *cpu, uint16 addr)
  77. {
  78. cpu_set_pc (cpu, addr);
  79. }
  80. void
  81. cpu_return (sim_cpu *cpu)
  82. {
  83. }
  84. /* Set the stack pointer and re-compute the current frame. */
  85. void
  86. cpu_set_sp (sim_cpu *cpu, uint16 val)
  87. {
  88. cpu->cpu_regs.sp = val;
  89. }
  90. uint16
  91. cpu_get_reg (sim_cpu* cpu, uint8 reg)
  92. {
  93. switch (reg)
  94. {
  95. case 0:
  96. return cpu_get_x (cpu);
  97. case 1:
  98. return cpu_get_y (cpu);
  99. case 2:
  100. return cpu_get_sp (cpu);
  101. case 3:
  102. return cpu_get_pc (cpu);
  103. default:
  104. return 0;
  105. }
  106. }
  107. uint16
  108. cpu_get_src_reg (sim_cpu* cpu, uint8 reg)
  109. {
  110. switch (reg)
  111. {
  112. case 0:
  113. return cpu_get_a (cpu);
  114. case 1:
  115. return cpu_get_b (cpu);
  116. case 2:
  117. return cpu_get_ccr (cpu);
  118. case 3:
  119. return cpu_get_tmp3 (cpu);
  120. case 4:
  121. return cpu_get_d (cpu);
  122. case 5:
  123. return cpu_get_x (cpu);
  124. case 6:
  125. return cpu_get_y (cpu);
  126. case 7:
  127. return cpu_get_sp (cpu);
  128. default:
  129. return 0;
  130. }
  131. }
  132. void
  133. cpu_set_dst_reg (sim_cpu* cpu, uint8 reg, uint16 val)
  134. {
  135. switch (reg)
  136. {
  137. case 0:
  138. cpu_set_a (cpu, val);
  139. break;
  140. case 1:
  141. cpu_set_b (cpu, val);
  142. break;
  143. case 2:
  144. cpu_set_ccr (cpu, val);
  145. break;
  146. case 3:
  147. cpu_set_tmp2 (cpu, val);
  148. break;
  149. case 4:
  150. cpu_set_d (cpu, val);
  151. break;
  152. case 5:
  153. cpu_set_x (cpu, val);
  154. break;
  155. case 6:
  156. cpu_set_y (cpu, val);
  157. break;
  158. case 7:
  159. cpu_set_sp (cpu, val);
  160. break;
  161. default:
  162. break;
  163. }
  164. }
  165. void
  166. cpu_set_reg (sim_cpu* cpu, uint8 reg, uint16 val)
  167. {
  168. switch (reg)
  169. {
  170. case 0:
  171. cpu_set_x (cpu, val);
  172. break;
  173. case 1:
  174. cpu_set_y (cpu, val);
  175. break;
  176. case 2:
  177. cpu_set_sp (cpu, val);
  178. break;
  179. case 3:
  180. cpu_set_pc (cpu, val);
  181. break;
  182. default:
  183. break;
  184. }
  185. }
  186. /* Returns the address of a 68HC12 indexed operand.
  187. Pre and post modifications are handled on the source register. */
  188. uint16
  189. cpu_get_indexed_operand_addr (sim_cpu* cpu, int restricted)
  190. {
  191. uint8 reg;
  192. uint16 sval;
  193. uint16 addr;
  194. uint8 code;
  195. code = cpu_fetch8 (cpu);
  196. /* n,r with 5-bit signed constant. */
  197. if ((code & 0x20) == 0)
  198. {
  199. reg = (code >> 6) & 3;
  200. sval = (code & 0x1f);
  201. if (code & 0x10)
  202. sval |= 0xfff0;
  203. addr = cpu_get_reg (cpu, reg);
  204. addr += sval;
  205. }
  206. /* Auto pre/post increment/decrement. */
  207. else if ((code & 0xc0) != 0xc0)
  208. {
  209. reg = (code >> 6) & 3;
  210. sval = (code & 0x0f);
  211. if (sval & 0x8)
  212. {
  213. sval |= 0xfff0;
  214. }
  215. else
  216. {
  217. sval = sval + 1;
  218. }
  219. addr = cpu_get_reg (cpu, reg);
  220. cpu_set_reg (cpu, reg, addr + sval);
  221. if ((code & 0x10) == 0)
  222. {
  223. addr += sval;
  224. }
  225. }
  226. /* [n,r] 16-bits offset indexed indirect. */
  227. else if ((code & 0x07) == 3)
  228. {
  229. if (restricted)
  230. {
  231. return 0;
  232. }
  233. reg = (code >> 3) & 0x03;
  234. addr = cpu_get_reg (cpu, reg);
  235. addr += cpu_fetch16 (cpu);
  236. addr = memory_read16 (cpu, addr);
  237. cpu_add_cycles (cpu, 1);
  238. }
  239. else if ((code & 0x4) == 0)
  240. {
  241. if (restricted)
  242. {
  243. return 0;
  244. }
  245. reg = (code >> 3) & 0x03;
  246. addr = cpu_get_reg (cpu, reg);
  247. if (code & 0x2)
  248. {
  249. sval = cpu_fetch16 (cpu);
  250. cpu_add_cycles (cpu, 1);
  251. }
  252. else
  253. {
  254. sval = cpu_fetch8 (cpu);
  255. if (code & 0x1)
  256. sval |= 0xff00;
  257. cpu_add_cycles (cpu, 1);
  258. }
  259. addr += sval;
  260. }
  261. else
  262. {
  263. reg = (code >> 3) & 0x03;
  264. addr = cpu_get_reg (cpu, reg);
  265. switch (code & 3)
  266. {
  267. case 0:
  268. addr += cpu_get_a (cpu);
  269. break;
  270. case 1:
  271. addr += cpu_get_b (cpu);
  272. break;
  273. case 2:
  274. addr += cpu_get_d (cpu);
  275. break;
  276. case 3:
  277. default:
  278. addr += cpu_get_d (cpu);
  279. addr = memory_read16 (cpu, addr);
  280. cpu_add_cycles (cpu, 1);
  281. break;
  282. }
  283. }
  284. return addr;
  285. }
  286. uint8
  287. cpu_get_indexed_operand8 (sim_cpu* cpu, int restricted)
  288. {
  289. uint16 addr;
  290. addr = cpu_get_indexed_operand_addr (cpu, restricted);
  291. return memory_read8 (cpu, addr);
  292. }
  293. uint16
  294. cpu_get_indexed_operand16 (sim_cpu* cpu, int restricted)
  295. {
  296. uint16 addr;
  297. addr = cpu_get_indexed_operand_addr (cpu, restricted);
  298. return memory_read16 (cpu, addr);
  299. }
  300. void
  301. cpu_move8 (sim_cpu *cpu, uint8 code)
  302. {
  303. uint8 src;
  304. uint16 addr;
  305. switch (code)
  306. {
  307. case 0x0b:
  308. src = cpu_fetch8 (cpu);
  309. addr = cpu_fetch16 (cpu);
  310. break;
  311. case 0x08:
  312. addr = cpu_get_indexed_operand_addr (cpu, 1);
  313. src = cpu_fetch8 (cpu);
  314. break;
  315. case 0x0c:
  316. addr = cpu_fetch16 (cpu);
  317. src = memory_read8 (cpu, addr);
  318. addr = cpu_fetch16 (cpu);
  319. break;
  320. case 0x09:
  321. addr = cpu_get_indexed_operand_addr (cpu, 1);
  322. src = memory_read8 (cpu, cpu_fetch16 (cpu));
  323. break;
  324. case 0x0d:
  325. src = cpu_get_indexed_operand8 (cpu, 1);
  326. addr = cpu_fetch16 (cpu);
  327. break;
  328. case 0x0a:
  329. src = cpu_get_indexed_operand8 (cpu, 1);
  330. addr = cpu_get_indexed_operand_addr (cpu, 1);
  331. break;
  332. default:
  333. sim_engine_abort (CPU_STATE (cpu), cpu, 0,
  334. "Invalid code 0x%0x -- internal error?", code);
  335. return;
  336. }
  337. memory_write8 (cpu, addr, src);
  338. }
  339. void
  340. cpu_move16 (sim_cpu *cpu, uint8 code)
  341. {
  342. uint16 src;
  343. uint16 addr;
  344. switch (code)
  345. {
  346. case 0x03:
  347. src = cpu_fetch16 (cpu);
  348. addr = cpu_fetch16 (cpu);
  349. break;
  350. case 0x00:
  351. addr = cpu_get_indexed_operand_addr (cpu, 1);
  352. src = cpu_fetch16 (cpu);
  353. break;
  354. case 0x04:
  355. addr = cpu_fetch16 (cpu);
  356. src = memory_read16 (cpu, addr);
  357. addr = cpu_fetch16 (cpu);
  358. break;
  359. case 0x01:
  360. addr = cpu_get_indexed_operand_addr (cpu, 1);
  361. src = memory_read16 (cpu, cpu_fetch16 (cpu));
  362. break;
  363. case 0x05:
  364. src = cpu_get_indexed_operand16 (cpu, 1);
  365. addr = cpu_fetch16 (cpu);
  366. break;
  367. case 0x02:
  368. src = cpu_get_indexed_operand16 (cpu, 1);
  369. addr = cpu_get_indexed_operand_addr (cpu, 1);
  370. break;
  371. default:
  372. sim_engine_abort (CPU_STATE (cpu), cpu, 0,
  373. "Invalid code 0x%0x -- internal error?", code);
  374. return;
  375. }
  376. memory_write16 (cpu, addr, src);
  377. }
  378. int
  379. cpu_initialize (SIM_DESC sd, sim_cpu *cpu)
  380. {
  381. sim_add_option_table (sd, 0, cpu_options);
  382. memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
  383. cpu->cpu_absolute_cycle = 0;
  384. cpu->cpu_current_cycle = 0;
  385. cpu->cpu_emul_syscall = 1;
  386. cpu->cpu_running = 1;
  387. cpu->cpu_stop_on_interrupt = 0;
  388. cpu->cpu_frequency = 8 * 1000 * 1000;
  389. cpu->cpu_use_elf_start = 0;
  390. cpu->cpu_elf_start = 0;
  391. cpu->cpu_use_local_config = 0;
  392. cpu->bank_start = 0;
  393. cpu->bank_end = 0;
  394. cpu->bank_shift = 0;
  395. cpu->cpu_config = M6811_NOSEC | M6811_NOCOP | M6811_ROMON |
  396. M6811_EEON;
  397. interrupts_initialize (sd, cpu);
  398. cpu->cpu_is_initialized = 1;
  399. return 0;
  400. }
  401. /* Reinitialize the processor after a reset. */
  402. int
  403. cpu_reset (sim_cpu *cpu)
  404. {
  405. /* Initialize the config register.
  406. It is only initialized at reset time. */
  407. memset (cpu->ios, 0, sizeof (cpu->ios));
  408. if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
  409. cpu->ios[M6811_INIT] = 0x1;
  410. else
  411. cpu->ios[M6811_INIT] = 0;
  412. /* Output compare registers set to 0xFFFF. */
  413. cpu->ios[M6811_TOC1_H] = 0xFF;
  414. cpu->ios[M6811_TOC1_L] = 0xFF;
  415. cpu->ios[M6811_TOC2_H] = 0xFF;
  416. cpu->ios[M6811_TOC2_L] = 0xFF;
  417. cpu->ios[M6811_TOC3_H] = 0xFF;
  418. cpu->ios[M6811_TOC4_L] = 0xFF;
  419. cpu->ios[M6811_TOC5_H] = 0xFF;
  420. cpu->ios[M6811_TOC5_L] = 0xFF;
  421. /* Setup the processor registers. */
  422. memset (&cpu->cpu_regs, 0, sizeof(cpu->cpu_regs));
  423. cpu->cpu_absolute_cycle = 0;
  424. cpu->cpu_current_cycle = 0;
  425. cpu->cpu_is_initialized = 0;
  426. /* Reset interrupts. */
  427. interrupts_reset (&cpu->cpu_interrupts);
  428. /* Reinitialize the CPU operating mode. */
  429. cpu->ios[M6811_HPRIO] = cpu->cpu_mode;
  430. return 0;
  431. }
  432. /* Reinitialize the processor after a reset. */
  433. int
  434. cpu_restart (sim_cpu *cpu)
  435. {
  436. uint16 addr;
  437. /* Get CPU starting address depending on the CPU mode. */
  438. if (cpu->cpu_use_elf_start == 0)
  439. {
  440. switch ((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA))
  441. {
  442. /* Single Chip */
  443. default:
  444. case 0 :
  445. addr = memory_read16 (cpu, 0xFFFE);
  446. break;
  447. /* Expanded Multiplexed */
  448. case M6811_MDA:
  449. addr = memory_read16 (cpu, 0xFFFE);
  450. break;
  451. /* Special Bootstrap */
  452. case M6811_SMOD:
  453. addr = 0;
  454. break;
  455. /* Factory Test */
  456. case M6811_MDA | M6811_SMOD:
  457. addr = memory_read16 (cpu, 0xFFFE);
  458. break;
  459. }
  460. }
  461. else
  462. {
  463. addr = cpu->cpu_elf_start;
  464. }
  465. /* Setup the processor registers. */
  466. cpu->cpu_insn_pc = addr;
  467. cpu->cpu_regs.pc = addr;
  468. cpu->cpu_regs.ccr = M6811_X_BIT | M6811_I_BIT | M6811_S_BIT;
  469. cpu->cpu_absolute_cycle = 0;
  470. cpu->cpu_is_initialized = 1;
  471. cpu->cpu_current_cycle = 0;
  472. cpu_call (cpu, addr);
  473. return 0;
  474. }
  475. void
  476. print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val, int mode)
  477. {
  478. while (desc->mask)
  479. {
  480. if (val & desc->mask)
  481. sim_io_printf (sd, "%s",
  482. mode == 0 ? desc->short_name : desc->long_name);
  483. desc++;
  484. }
  485. }
  486. void
  487. print_io_byte (SIM_DESC sd, const char *name, io_reg_desc *desc,
  488. uint8 val, uint16 addr)
  489. {
  490. sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%02x ", name, addr, val);
  491. if (desc)
  492. print_io_reg_desc (sd, desc, val, 0);
  493. }
  494. void
  495. print_io_word (SIM_DESC sd, const char *name, io_reg_desc *desc,
  496. uint16 val, uint16 addr)
  497. {
  498. sim_io_printf (sd, " %-9.9s @ 0x%04x 0x%04x ", name, addr, val);
  499. if (desc)
  500. print_io_reg_desc (sd, desc, val, 0);
  501. }
  502. void
  503. cpu_ccr_update_tst8 (sim_cpu *proc, uint8 val)
  504. {
  505. cpu_set_ccr_V (proc, 0);
  506. cpu_set_ccr_N (proc, val & 0x80 ? 1 : 0);
  507. cpu_set_ccr_Z (proc, val == 0 ? 1 : 0);
  508. }
  509. uint16
  510. cpu_fetch_relbranch (sim_cpu *cpu)
  511. {
  512. uint16 addr = (uint16) cpu_fetch8 (cpu);
  513. if (addr & 0x0080)
  514. {
  515. addr |= 0xFF00;
  516. }
  517. addr += cpu->cpu_regs.pc;
  518. return addr;
  519. }
  520. uint16
  521. cpu_fetch_relbranch16 (sim_cpu *cpu)
  522. {
  523. uint16 addr = cpu_fetch16 (cpu);
  524. addr += cpu->cpu_regs.pc;
  525. return addr;
  526. }
  527. /* Push all the CPU registers (when an interruption occurs). */
  528. void
  529. cpu_push_all (sim_cpu *cpu)
  530. {
  531. if (cpu->cpu_configured_arch->arch == bfd_arch_m68hc11)
  532. {
  533. cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.pc);
  534. cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.iy);
  535. cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.ix);
  536. cpu_m68hc11_push_uint16 (cpu, cpu->cpu_regs.d);
  537. cpu_m68hc11_push_uint8 (cpu, cpu->cpu_regs.ccr);
  538. }
  539. else
  540. {
  541. cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.pc);
  542. cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.iy);
  543. cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.ix);
  544. cpu_m68hc12_push_uint16 (cpu, cpu->cpu_regs.d);
  545. cpu_m68hc12_push_uint8 (cpu, cpu->cpu_regs.ccr);
  546. }
  547. }
  548. /* Simulation of the dbcc/ibcc/tbcc 68HC12 conditional branch operations. */
  549. void
  550. cpu_dbcc (sim_cpu* cpu)
  551. {
  552. uint8 code;
  553. uint16 addr;
  554. uint16 inc;
  555. uint16 reg;
  556. code = cpu_fetch8 (cpu);
  557. switch (code & 0xc0)
  558. {
  559. case 0x80: /* ibcc */
  560. inc = 1;
  561. break;
  562. case 0x40: /* tbcc */
  563. inc = 0;
  564. break;
  565. case 0: /* dbcc */
  566. inc = -1;
  567. break;
  568. default:
  569. abort ();
  570. break;
  571. }
  572. addr = cpu_fetch8 (cpu);
  573. if (code & 0x10)
  574. addr |= 0xff00;
  575. addr += cpu_get_pc (cpu);
  576. reg = cpu_get_src_reg (cpu, code & 0x07);
  577. reg += inc;
  578. /* Branch according to register value. */
  579. if ((reg != 0 && (code & 0x20)) || (reg == 0 && !(code & 0x20)))
  580. {
  581. cpu_set_pc (cpu, addr);
  582. }
  583. cpu_set_dst_reg (cpu, code & 0x07, reg);
  584. }
  585. void
  586. cpu_exg (sim_cpu* cpu, uint8 code)
  587. {
  588. uint8 r1, r2;
  589. uint16 src1;
  590. uint16 src2;
  591. r1 = (code >> 4) & 0x07;
  592. r2 = code & 0x07;
  593. if (code & 0x80)
  594. {
  595. src1 = cpu_get_src_reg (cpu, r1);
  596. src2 = cpu_get_src_reg (cpu, r2);
  597. if (r2 == 1 || r2 == 2)
  598. src2 |= 0xff00;
  599. cpu_set_dst_reg (cpu, r2, src1);
  600. cpu_set_dst_reg (cpu, r1, src2);
  601. }
  602. else
  603. {
  604. src1 = cpu_get_src_reg (cpu, r1);
  605. /* Sign extend the 8-bit registers (A, B, CCR). */
  606. if ((r1 == 0 || r1 == 1 || r1 == 2) && (src1 & 0x80))
  607. src1 |= 0xff00;
  608. cpu_set_dst_reg (cpu, r2, src1);
  609. }
  610. }
  611. /* Handle special instructions. */
  612. void
  613. cpu_special (sim_cpu *cpu, enum M6811_Special special)
  614. {
  615. switch (special)
  616. {
  617. case M6811_RTI:
  618. {
  619. uint8 ccr;
  620. ccr = cpu_m68hc11_pop_uint8 (cpu);
  621. cpu_set_ccr (cpu, ccr);
  622. cpu_set_d (cpu, cpu_m68hc11_pop_uint16 (cpu));
  623. cpu_set_x (cpu, cpu_m68hc11_pop_uint16 (cpu));
  624. cpu_set_y (cpu, cpu_m68hc11_pop_uint16 (cpu));
  625. cpu_set_pc (cpu, cpu_m68hc11_pop_uint16 (cpu));
  626. cpu_return (cpu);
  627. break;
  628. }
  629. case M6812_RTI:
  630. {
  631. uint8 ccr;
  632. ccr = cpu_m68hc12_pop_uint8 (cpu);
  633. cpu_set_ccr (cpu, ccr);
  634. cpu_set_d (cpu, cpu_m68hc12_pop_uint16 (cpu));
  635. cpu_set_x (cpu, cpu_m68hc12_pop_uint16 (cpu));
  636. cpu_set_y (cpu, cpu_m68hc12_pop_uint16 (cpu));
  637. cpu_set_pc (cpu, cpu_m68hc12_pop_uint16 (cpu));
  638. cpu_return (cpu);
  639. break;
  640. }
  641. case M6811_WAI:
  642. /* In the ELF-start mode, we are in a special mode where
  643. the WAI corresponds to an exit. */
  644. if (cpu->cpu_use_elf_start)
  645. {
  646. cpu_set_pc (cpu, cpu->cpu_insn_pc);
  647. sim_engine_halt (CPU_STATE (cpu), cpu,
  648. NULL, NULL_CIA, sim_exited,
  649. cpu_get_d (cpu));
  650. return;
  651. }
  652. /* SCz: not correct... */
  653. cpu_push_all (cpu);
  654. break;
  655. case M6811_SWI:
  656. interrupts_raise (&cpu->cpu_interrupts, M6811_INT_SWI);
  657. interrupts_process (&cpu->cpu_interrupts);
  658. break;
  659. case M6811_EMUL_SYSCALL:
  660. case M6811_ILLEGAL:
  661. if (cpu->cpu_emul_syscall)
  662. {
  663. uint8 op = memory_read8 (cpu,
  664. cpu_get_pc (cpu) - 1);
  665. if (op == 0x41)
  666. {
  667. cpu_set_pc (cpu, cpu->cpu_insn_pc);
  668. sim_engine_halt (CPU_STATE (cpu), cpu,
  669. NULL, NULL_CIA, sim_exited,
  670. cpu_get_d (cpu));
  671. return;
  672. }
  673. else
  674. {
  675. emul_os (op, cpu);
  676. }
  677. return;
  678. }
  679. interrupts_raise (&cpu->cpu_interrupts, M6811_INT_ILLEGAL);
  680. interrupts_process (&cpu->cpu_interrupts);
  681. break;
  682. case M6811_TEST:
  683. case M6812_BGND:
  684. {
  685. SIM_DESC sd;
  686. sd = CPU_STATE (cpu);
  687. /* Breakpoint instruction if we are under gdb. */
  688. if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG)
  689. {
  690. cpu->cpu_regs.pc --;
  691. sim_engine_halt (CPU_STATE (cpu), cpu,
  692. 0, cpu_get_pc (cpu), sim_stopped,
  693. SIM_SIGTRAP);
  694. }
  695. /* else this is a nop but not in test factory mode. */
  696. break;
  697. }
  698. case M6812_IDIVS:
  699. {
  700. int32 src1 = (int16) cpu_get_d (cpu);
  701. int32 src2 = (int16) cpu_get_x (cpu);
  702. if (src2 == 0)
  703. {
  704. cpu_set_ccr_C (cpu, 1);
  705. }
  706. else
  707. {
  708. cpu_set_d (cpu, src1 % src2);
  709. src1 = src1 / src2;
  710. cpu_set_x (cpu, src1);
  711. cpu_set_ccr_C (cpu, 0);
  712. cpu_set_ccr_Z (cpu, src1 == 0);
  713. cpu_set_ccr_N (cpu, src1 & 0x8000);
  714. cpu_set_ccr_V (cpu, src1 >= 32768 || src1 < -32768);
  715. }
  716. }
  717. break;
  718. case M6812_EDIV:
  719. {
  720. uint32 src1 = (uint32) cpu_get_x (cpu);
  721. uint32 src2 = (uint32) (cpu_get_y (cpu) << 16)
  722. | (uint32) (cpu_get_d (cpu));
  723. if (src1 == 0)
  724. {
  725. cpu_set_ccr_C (cpu, 1);
  726. }
  727. else
  728. {
  729. cpu_set_ccr_C (cpu, 0);
  730. cpu_set_d (cpu, src2 % src1);
  731. src2 = src2 / src1;
  732. cpu_set_y (cpu, src2);
  733. cpu_set_ccr_Z (cpu, src2 == 0);
  734. cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
  735. cpu_set_ccr_V (cpu, (src2 & 0xffff0000) != 0);
  736. }
  737. }
  738. break;
  739. case M6812_EDIVS:
  740. {
  741. int32 src1 = (int16) cpu_get_x (cpu);
  742. int32 src2 = (uint32) (cpu_get_y (cpu) << 16)
  743. | (uint32) (cpu_get_d (cpu));
  744. if (src1 == 0)
  745. {
  746. cpu_set_ccr_C (cpu, 1);
  747. }
  748. else
  749. {
  750. cpu_set_ccr_C (cpu, 0);
  751. cpu_set_d (cpu, src2 % src1);
  752. src2 = src2 / src1;
  753. cpu_set_y (cpu, src2);
  754. cpu_set_ccr_Z (cpu, src2 == 0);
  755. cpu_set_ccr_N (cpu, (src2 & 0x8000) != 0);
  756. cpu_set_ccr_V (cpu, src2 > 32767 || src2 < -32768);
  757. }
  758. }
  759. break;
  760. case M6812_EMULS:
  761. {
  762. int32 src1, src2;
  763. src1 = (int16) cpu_get_d (cpu);
  764. src2 = (int16) cpu_get_y (cpu);
  765. src1 = src1 * src2;
  766. cpu_set_d (cpu, src1 & 0x0ffff);
  767. cpu_set_y (cpu, src1 >> 16);
  768. cpu_set_ccr_Z (cpu, src1 == 0);
  769. cpu_set_ccr_N (cpu, (src1 & 0x80000000) != 0);
  770. cpu_set_ccr_C (cpu, (src1 & 0x00008000) != 0);
  771. }
  772. break;
  773. case M6812_EMACS:
  774. {
  775. int32 src1, src2;
  776. uint16 addr;
  777. addr = cpu_fetch16 (cpu);
  778. src1 = (int16) memory_read16 (cpu, cpu_get_x (cpu));
  779. src2 = (int16) memory_read16 (cpu, cpu_get_y (cpu));
  780. src1 = src1 * src2;
  781. src2 = (((uint32) memory_read16 (cpu, addr)) << 16)
  782. | (uint32) memory_read16 (cpu, addr + 2);
  783. memory_write16 (cpu, addr, (src1 + src2) >> 16);
  784. memory_write16 (cpu, addr + 2, (src1 + src2));
  785. }
  786. break;
  787. case M6812_CALL:
  788. {
  789. uint8 page;
  790. uint16 addr;
  791. addr = cpu_fetch16 (cpu);
  792. page = cpu_fetch8 (cpu);
  793. cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
  794. cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
  795. cpu_set_page (cpu, page);
  796. cpu_set_pc (cpu, addr);
  797. }
  798. break;
  799. case M6812_CALL_INDIRECT:
  800. {
  801. uint8 code;
  802. uint16 addr;
  803. uint8 page;
  804. code = memory_read8 (cpu, cpu_get_pc (cpu));
  805. /* Indirect addressing call has the page specified in the
  806. memory location pointed to by the address. */
  807. if ((code & 0xE3) == 0xE3)
  808. {
  809. addr = cpu_get_indexed_operand_addr (cpu, 0);
  810. page = memory_read8 (cpu, addr + 2);
  811. addr = memory_read16 (cpu, addr);
  812. }
  813. else
  814. {
  815. /* Otherwise, page is in the opcode. */
  816. addr = cpu_get_indexed_operand16 (cpu, 0);
  817. page = cpu_fetch8 (cpu);
  818. }
  819. cpu_m68hc12_push_uint16 (cpu, cpu_get_pc (cpu));
  820. cpu_m68hc12_push_uint8 (cpu, cpu_get_page (cpu));
  821. cpu_set_page (cpu, page);
  822. cpu_set_pc (cpu, addr);
  823. }
  824. break;
  825. case M6812_RTC:
  826. {
  827. uint8 page = cpu_m68hc12_pop_uint8 (cpu);
  828. uint16 addr = cpu_m68hc12_pop_uint16 (cpu);
  829. cpu_set_page (cpu, page);
  830. cpu_set_pc (cpu, addr);
  831. }
  832. break;
  833. case M6812_ETBL:
  834. default:
  835. sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
  836. cpu_get_pc (cpu), sim_stopped,
  837. SIM_SIGILL);
  838. break;
  839. }
  840. }
  841. void
  842. cpu_single_step (sim_cpu *cpu)
  843. {
  844. cpu->cpu_current_cycle = 0;
  845. cpu->cpu_insn_pc = cpu_get_pc (cpu);
  846. /* Handle the pending interrupts. If an interrupt is handled,
  847. treat this as an single step. */
  848. if (interrupts_process (&cpu->cpu_interrupts))
  849. {
  850. cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
  851. return;
  852. }
  853. /* printf("PC = 0x%04x\n", cpu_get_pc (cpu));*/
  854. cpu->cpu_interpretor (cpu);
  855. cpu->cpu_absolute_cycle += cpu->cpu_current_cycle;
  856. }
  857. /* VARARGS */
  858. void
  859. sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
  860. uint16 addr, const char *message, ...)
  861. {
  862. char buf[1024];
  863. va_list args;
  864. va_start (args, message);
  865. vsprintf (buf, message, args);
  866. va_end (args);
  867. sim_io_printf (CPU_STATE (cpu), "%s\n", buf);
  868. cpu_memory_exception (cpu, excep, addr, buf);
  869. }
  870. void
  871. cpu_memory_exception (sim_cpu *cpu, SIM_SIGNAL excep,
  872. uint16 addr, const char *message)
  873. {
  874. if (cpu->cpu_running == 0)
  875. return;
  876. cpu_set_pc (cpu, cpu->cpu_insn_pc);
  877. sim_engine_halt (CPU_STATE (cpu), cpu, NULL,
  878. cpu_get_pc (cpu), sim_stopped, excep);
  879. #if 0
  880. cpu->mem_exception = excep;
  881. cpu->fault_addr = addr;
  882. cpu->fault_msg = strdup (message);
  883. if (cpu->cpu_use_handler)
  884. {
  885. longjmp (&cpu->cpu_exception_handler, 1);
  886. }
  887. (* cpu->callback->printf_filtered)
  888. (cpu->callback, "Fault at 0x%04x: %s\n", addr, message);
  889. #endif
  890. }
  891. void
  892. cpu_info (SIM_DESC sd, sim_cpu *cpu)
  893. {
  894. sim_io_printf (sd, "CPU info:\n");
  895. sim_io_printf (sd, " Absolute cycle: %s\n",
  896. cycle_to_string (cpu, cpu->cpu_absolute_cycle,
  897. PRINT_TIME | PRINT_CYCLE));
  898. sim_io_printf (sd, " Syscall emulation: %s\n",
  899. cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
  900. sim_io_printf (sd, " Memory errors detection: %s\n",
  901. cpu->cpu_check_memory ? "yes" : "no");
  902. sim_io_printf (sd, " Stop on interrupt: %s\n",
  903. cpu->cpu_stop_on_interrupt ? "yes" : "no");
  904. }