interp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /* Simulator for Xilinx MicroBlaze processor
  2. Copyright 2009-2022 Free Software Foundation, Inc.
  3. This file is part of GDB, the GNU debugger.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, see <http://www.gnu.org/licenses/>. */
  14. /* This must come before any other includes. */
  15. #include "defs.h"
  16. #include <signal.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #include "bfd.h"
  21. #include "sim/callback.h"
  22. #include "libiberty.h"
  23. #include "sim/sim.h"
  24. #include "sim-main.h"
  25. #include "sim-options.h"
  26. #include "sim-signal.h"
  27. #include "sim-syscall.h"
  28. #include "microblaze-dis.h"
  29. #define target_big_endian (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
  30. static unsigned long
  31. microblaze_extract_unsigned_integer (unsigned char *addr, int len)
  32. {
  33. unsigned long retval;
  34. unsigned char *p;
  35. unsigned char *startaddr = (unsigned char *)addr;
  36. unsigned char *endaddr = startaddr + len;
  37. if (len > (int) sizeof (unsigned long))
  38. printf ("That operation is not available on integers of more than "
  39. "%zu bytes.", sizeof (unsigned long));
  40. /* Start at the most significant end of the integer, and work towards
  41. the least significant. */
  42. retval = 0;
  43. if (!target_big_endian)
  44. {
  45. for (p = endaddr; p > startaddr;)
  46. retval = (retval << 8) | * -- p;
  47. }
  48. else
  49. {
  50. for (p = startaddr; p < endaddr;)
  51. retval = (retval << 8) | * p ++;
  52. }
  53. return retval;
  54. }
  55. static void
  56. microblaze_store_unsigned_integer (unsigned char *addr, int len,
  57. unsigned long val)
  58. {
  59. unsigned char *p;
  60. unsigned char *startaddr = (unsigned char *)addr;
  61. unsigned char *endaddr = startaddr + len;
  62. if (!target_big_endian)
  63. {
  64. for (p = startaddr; p < endaddr;)
  65. {
  66. *p++ = val & 0xff;
  67. val >>= 8;
  68. }
  69. }
  70. else
  71. {
  72. for (p = endaddr; p > startaddr;)
  73. {
  74. *--p = val & 0xff;
  75. val >>= 8;
  76. }
  77. }
  78. }
  79. static void
  80. set_initial_gprs (SIM_CPU *cpu)
  81. {
  82. int i;
  83. long space;
  84. /* Set up machine just out of reset. */
  85. PC = 0;
  86. MSR = 0;
  87. /* Clean out the GPRs */
  88. for (i = 0; i < 32; i++)
  89. CPU.regs[i] = 0;
  90. CPU.insts = 0;
  91. CPU.cycles = 0;
  92. CPU.imm_enable = 0;
  93. }
  94. static int tracing = 0;
  95. void
  96. sim_engine_run (SIM_DESC sd,
  97. int next_cpu_nr, /* ignore */
  98. int nr_cpus, /* ignore */
  99. int siggnal) /* ignore */
  100. {
  101. SIM_CPU *cpu = STATE_CPU (sd, 0);
  102. int needfetch;
  103. signed_4 inst;
  104. enum microblaze_instr op;
  105. int memops;
  106. int bonus_cycles;
  107. int insts;
  108. int w;
  109. int cycs;
  110. signed_4 WLhash;
  111. unsigned_1 carry;
  112. bool imm_unsigned;
  113. short ra, rb, rd;
  114. long immword;
  115. unsigned_4 oldpc, newpc;
  116. short delay_slot_enable;
  117. short branch_taken;
  118. short num_delay_slot; /* UNUSED except as reqd parameter */
  119. enum microblaze_instr_type insn_type;
  120. memops = 0;
  121. bonus_cycles = 0;
  122. insts = 0;
  123. while (1)
  124. {
  125. /* Fetch the initial instructions that we'll decode. */
  126. inst = MEM_RD_WORD (PC & 0xFFFFFFFC);
  127. op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
  128. &num_delay_slot);
  129. if (op == invalid_inst)
  130. fprintf (stderr, "Unknown instruction 0x%04x", inst);
  131. if (tracing)
  132. fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
  133. rd = GET_RD;
  134. rb = GET_RB;
  135. ra = GET_RA;
  136. /* immword = IMM_W; */
  137. oldpc = PC;
  138. delay_slot_enable = 0;
  139. branch_taken = 0;
  140. if (op == microblaze_brk)
  141. sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_stopped, SIM_SIGTRAP);
  142. else if (inst == MICROBLAZE_HALT_INST)
  143. {
  144. insts += 1;
  145. bonus_cycles++;
  146. TRACE_INSN (cpu, "HALT (%i)", RETREG);
  147. sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_exited, RETREG);
  148. }
  149. else
  150. {
  151. switch(op)
  152. {
  153. #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
  154. case NAME: \
  155. TRACE_INSN (cpu, #NAME); \
  156. ACTION; \
  157. break;
  158. #include "microblaze.isa"
  159. #undef INSTRUCTION
  160. default:
  161. sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled,
  162. SIM_SIGILL);
  163. fprintf (stderr, "ERROR: Unknown opcode\n");
  164. }
  165. /* Make R0 consistent */
  166. CPU.regs[0] = 0;
  167. /* Check for imm instr */
  168. if (op == imm)
  169. IMM_ENABLE = 1;
  170. else
  171. IMM_ENABLE = 0;
  172. /* Update cycle counts */
  173. insts ++;
  174. if (insn_type == memory_store_inst || insn_type == memory_load_inst)
  175. memops++;
  176. if (insn_type == mult_inst)
  177. bonus_cycles++;
  178. if (insn_type == barrel_shift_inst)
  179. bonus_cycles++;
  180. if (insn_type == anyware_inst)
  181. bonus_cycles++;
  182. if (insn_type == div_inst)
  183. bonus_cycles += 33;
  184. if ((insn_type == branch_inst || insn_type == return_inst)
  185. && branch_taken)
  186. {
  187. /* Add an extra cycle for taken branches */
  188. bonus_cycles++;
  189. /* For branch instructions handle the instruction in the delay slot */
  190. if (delay_slot_enable)
  191. {
  192. newpc = PC;
  193. PC = oldpc + INST_SIZE;
  194. inst = MEM_RD_WORD (PC & 0xFFFFFFFC);
  195. op = get_insn_microblaze (inst, &imm_unsigned, &insn_type,
  196. &num_delay_slot);
  197. if (op == invalid_inst)
  198. fprintf (stderr, "Unknown instruction 0x%04x", inst);
  199. if (tracing)
  200. fprintf (stderr, "%.4x: inst = %.4x ", PC, inst);
  201. rd = GET_RD;
  202. rb = GET_RB;
  203. ra = GET_RA;
  204. /* immword = IMM_W; */
  205. if (op == microblaze_brk)
  206. {
  207. if (STATE_VERBOSE_P (sd))
  208. fprintf (stderr, "Breakpoint set in delay slot "
  209. "(at address 0x%x) will not be honored\n", PC);
  210. /* ignore the breakpoint */
  211. }
  212. else if (insn_type == branch_inst || insn_type == return_inst)
  213. {
  214. if (STATE_VERBOSE_P (sd))
  215. fprintf (stderr, "Cannot have branch or return instructions "
  216. "in delay slot (at address 0x%x)\n", PC);
  217. sim_engine_halt (sd, NULL, NULL, NULL_CIA, sim_signalled,
  218. SIM_SIGILL);
  219. }
  220. else
  221. {
  222. switch(op)
  223. {
  224. #define INSTRUCTION(NAME, OPCODE, TYPE, ACTION) \
  225. case NAME: \
  226. ACTION; \
  227. break;
  228. #include "microblaze.isa"
  229. #undef INSTRUCTION
  230. default:
  231. sim_engine_halt (sd, NULL, NULL, NULL_CIA,
  232. sim_signalled, SIM_SIGILL);
  233. fprintf (stderr, "ERROR: Unknown opcode at 0x%x\n", PC);
  234. }
  235. /* Update cycle counts */
  236. insts++;
  237. if (insn_type == memory_store_inst
  238. || insn_type == memory_load_inst)
  239. memops++;
  240. if (insn_type == mult_inst)
  241. bonus_cycles++;
  242. if (insn_type == barrel_shift_inst)
  243. bonus_cycles++;
  244. if (insn_type == anyware_inst)
  245. bonus_cycles++;
  246. if (insn_type == div_inst)
  247. bonus_cycles += 33;
  248. }
  249. /* Restore the PC */
  250. PC = newpc;
  251. /* Make R0 consistent */
  252. CPU.regs[0] = 0;
  253. /* Check for imm instr */
  254. if (op == imm)
  255. IMM_ENABLE = 1;
  256. else
  257. IMM_ENABLE = 0;
  258. }
  259. else
  260. {
  261. if (op == brki && IMM == 8)
  262. {
  263. RETREG = sim_syscall (cpu, CPU.regs[12], CPU.regs[5],
  264. CPU.regs[6], CPU.regs[7],
  265. CPU.regs[8]);
  266. PC = RD + INST_SIZE;
  267. }
  268. /* no delay slot: increment cycle count */
  269. bonus_cycles++;
  270. }
  271. }
  272. }
  273. if (tracing)
  274. fprintf (stderr, "\n");
  275. if (sim_events_tick (sd))
  276. sim_events_process (sd);
  277. }
  278. /* Hide away the things we've cached while executing. */
  279. /* CPU.pc = pc; */
  280. CPU.insts += insts; /* instructions done ... */
  281. CPU.cycles += insts; /* and each takes a cycle */
  282. CPU.cycles += bonus_cycles; /* and extra cycles for branches */
  283. CPU.cycles += memops; /* and memop cycle delays */
  284. }
  285. static int
  286. microblaze_reg_store (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
  287. {
  288. if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
  289. {
  290. if (length == 4)
  291. {
  292. /* misalignment safe */
  293. long ival = microblaze_extract_unsigned_integer (memory, 4);
  294. if (rn < NUM_REGS)
  295. CPU.regs[rn] = ival;
  296. else
  297. CPU.spregs[rn-NUM_REGS] = ival;
  298. return 4;
  299. }
  300. else
  301. return 0;
  302. }
  303. else
  304. return 0;
  305. }
  306. static int
  307. microblaze_reg_fetch (SIM_CPU *cpu, int rn, unsigned char *memory, int length)
  308. {
  309. long ival;
  310. if (rn < NUM_REGS + NUM_SPECIAL && rn >= 0)
  311. {
  312. if (length == 4)
  313. {
  314. if (rn < NUM_REGS)
  315. ival = CPU.regs[rn];
  316. else
  317. ival = CPU.spregs[rn-NUM_REGS];
  318. /* misalignment-safe */
  319. microblaze_store_unsigned_integer (memory, 4, ival);
  320. return 4;
  321. }
  322. else
  323. return 0;
  324. }
  325. else
  326. return 0;
  327. }
  328. void
  329. sim_info (SIM_DESC sd, int verbose)
  330. {
  331. SIM_CPU *cpu = STATE_CPU (sd, 0);
  332. host_callback *callback = STATE_CALLBACK (sd);
  333. callback->printf_filtered (callback, "\n\n# instructions executed %10d\n",
  334. CPU.insts);
  335. callback->printf_filtered (callback, "# cycles %10d\n",
  336. (CPU.cycles) ? CPU.cycles+2 : 0);
  337. }
  338. static sim_cia
  339. microblaze_pc_get (sim_cpu *cpu)
  340. {
  341. return cpu->microblaze_cpu.spregs[0];
  342. }
  343. static void
  344. microblaze_pc_set (sim_cpu *cpu, sim_cia pc)
  345. {
  346. cpu->microblaze_cpu.spregs[0] = pc;
  347. }
  348. static void
  349. free_state (SIM_DESC sd)
  350. {
  351. if (STATE_MODULES (sd) != NULL)
  352. sim_module_uninstall (sd);
  353. sim_cpu_free_all (sd);
  354. sim_state_free (sd);
  355. }
  356. SIM_DESC
  357. sim_open (SIM_OPEN_KIND kind, host_callback *cb,
  358. struct bfd *abfd, char * const *argv)
  359. {
  360. int i;
  361. SIM_DESC sd = sim_state_alloc (kind, cb);
  362. SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  363. /* The cpu data is kept in a separately allocated chunk of memory. */
  364. if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
  365. {
  366. free_state (sd);
  367. return 0;
  368. }
  369. if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
  370. {
  371. free_state (sd);
  372. return 0;
  373. }
  374. /* The parser will print an error message for us, so we silently return. */
  375. if (sim_parse_args (sd, argv) != SIM_RC_OK)
  376. {
  377. free_state (sd);
  378. return 0;
  379. }
  380. /* Check for/establish the a reference program image. */
  381. if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
  382. {
  383. free_state (sd);
  384. return 0;
  385. }
  386. /* Configure/verify the target byte order and other runtime
  387. configuration options. */
  388. if (sim_config (sd) != SIM_RC_OK)
  389. {
  390. sim_module_uninstall (sd);
  391. return 0;
  392. }
  393. if (sim_post_argv_init (sd) != SIM_RC_OK)
  394. {
  395. /* Uninstall the modules to avoid memory leaks,
  396. file descriptor leaks, etc. */
  397. sim_module_uninstall (sd);
  398. return 0;
  399. }
  400. /* CPU specific initialization. */
  401. for (i = 0; i < MAX_NR_PROCESSORS; ++i)
  402. {
  403. SIM_CPU *cpu = STATE_CPU (sd, i);
  404. CPU_REG_FETCH (cpu) = microblaze_reg_fetch;
  405. CPU_REG_STORE (cpu) = microblaze_reg_store;
  406. CPU_PC_FETCH (cpu) = microblaze_pc_get;
  407. CPU_PC_STORE (cpu) = microblaze_pc_set;
  408. set_initial_gprs (cpu);
  409. }
  410. /* Default to a 8 Mbyte (== 2^23) memory space. */
  411. sim_do_commandf (sd, "memory-size 0x800000");
  412. return sd;
  413. }
  414. SIM_RC
  415. sim_create_inferior (SIM_DESC sd, struct bfd *prog_bfd,
  416. char * const *argv, char * const *env)
  417. {
  418. SIM_CPU *cpu = STATE_CPU (sd, 0);
  419. PC = bfd_get_start_address (prog_bfd);
  420. return SIM_RC_OK;
  421. }