psim.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208
  1. /* This file is part of the program psim.
  2. Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #ifndef _PSIM_C_
  15. #define _PSIM_C_
  16. #include "cpu.h" /* includes psim.h */
  17. #include "idecode.h"
  18. #include "options.h"
  19. #include "tree.h"
  20. #include <signal.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24. #include <setjmp.h>
  25. #include <string.h>
  26. #include "bfd.h"
  27. #include "libiberty.h"
  28. #include "gdb/signals.h"
  29. /* system structure, actual size of processor array determined at
  30. runtime */
  31. struct _psim {
  32. event_queue *events;
  33. device *devices;
  34. mon *monitor;
  35. os_emul *os_emulation;
  36. core *memory;
  37. /* escape routine for inner functions */
  38. void *path_to_halt;
  39. void *path_to_restart;
  40. /* status from last halt */
  41. psim_status halt_status;
  42. /* the processors proper */
  43. int nr_cpus;
  44. int last_cpu; /* CPU that last (tried to) execute an instruction */
  45. cpu *processors[MAX_NR_PROCESSORS];
  46. };
  47. enum bfd_endian current_target_byte_order;
  48. int current_environment;
  49. int current_alignment;
  50. int current_floating_point;
  51. int current_model_issue = MODEL_ISSUE_IGNORE;
  52. int current_stdio = DO_USE_STDIO;
  53. model_enum current_model = WITH_DEFAULT_MODEL;
  54. /* create the device tree */
  55. INLINE_PSIM\
  56. (device *)
  57. psim_tree(void)
  58. {
  59. device *root = tree_parse(NULL, "core");
  60. tree_parse(root, "/aliases");
  61. tree_parse(root, "/options");
  62. tree_parse(root, "/chosen");
  63. tree_parse(root, "/packages");
  64. tree_parse(root, "/cpus");
  65. tree_parse(root, "/openprom");
  66. tree_parse(root, "/openprom/init");
  67. tree_parse(root, "/openprom/trace");
  68. tree_parse(root, "/openprom/options");
  69. return root;
  70. }
  71. STATIC_INLINE_PSIM\
  72. (const char *)
  73. find_arg(const char *err_msg,
  74. int *ptr_to_argp,
  75. char * const *argv)
  76. {
  77. *ptr_to_argp += 1;
  78. if (argv[*ptr_to_argp] == NULL)
  79. error(err_msg);
  80. return argv[*ptr_to_argp];
  81. }
  82. INLINE_PSIM\
  83. (void)
  84. psim_usage (int verbose, int help, SIM_OPEN_KIND kind)
  85. {
  86. printf_filtered("Usage:\n");
  87. printf_filtered("\n");
  88. printf_filtered("\tpsim [ <psim-option> ... ] <image> [ <image-arg> ... ]\n");
  89. printf_filtered("\n");
  90. printf_filtered("Where\n");
  91. printf_filtered("\n");
  92. printf_filtered("\t<image> Name of the PowerPC program to run.\n");
  93. if (verbose) {
  94. printf_filtered("\t This can either be a PowerPC binary or\n");
  95. printf_filtered("\t a text file containing a device tree\n");
  96. printf_filtered("\t specification.\n");
  97. printf_filtered("\t PSIM will attempt to determine from the\n");
  98. printf_filtered("\t specified <image> the intended emulation\n");
  99. printf_filtered("\t environment.\n");
  100. printf_filtered("\t If PSIM gets it wrong, the emulation\n");
  101. printf_filtered("\t environment can be specified using the\n");
  102. printf_filtered("\t `-e' option (described below).\n");
  103. printf_filtered("\n"); }
  104. printf_filtered("\t<image-arg> Argument to be passed to <image>\n");
  105. if (verbose) {
  106. printf_filtered("\t These arguments will be passed to\n");
  107. printf_filtered("\t <image> (as standard C argv, argc)\n");
  108. printf_filtered("\t when <image> is started.\n");
  109. printf_filtered("\n"); }
  110. printf_filtered("\t<psim-option> See below\n");
  111. printf_filtered("\n");
  112. printf_filtered("The following are valid <psim-option>s:\n");
  113. printf_filtered("\n");
  114. printf_filtered("\t-c <count> Limit the simulation to <count> iterations\n");
  115. if (verbose) {
  116. printf_filtered("\n");
  117. }
  118. printf_filtered("\t-i or -i2 Print instruction counting statistics\n");
  119. if (verbose) {
  120. printf_filtered("\t Specify -i2 for a more detailed display\n");
  121. printf_filtered("\n");
  122. }
  123. printf_filtered("\t-I Print execution unit statistics\n");
  124. if (verbose) { printf_filtered("\n"); }
  125. printf_filtered("\t-e <os-emul> specify an OS or platform to model\n");
  126. if (verbose) {
  127. printf_filtered("\t Can be any of the following:\n");
  128. printf_filtered("\t bug - OEA + MOTO BUG ROM calls\n");
  129. printf_filtered("\t netbsd - UEA + NetBSD system calls\n");
  130. printf_filtered("\t solaris - UEA + Solaris system calls\n");
  131. printf_filtered("\t linux - UEA + Linux system calls\n");
  132. printf_filtered("\t chirp - OEA + a few OpenBoot calls\n");
  133. printf_filtered("\n"); }
  134. printf_filtered("\t-E <endian> Specify the endianness of the target\n");
  135. if (verbose) {
  136. printf_filtered("\t Can be any of the following:\n");
  137. printf_filtered("\t big - big endian target\n");
  138. printf_filtered("\t little - little endian target\n");
  139. printf_filtered("\n"); }
  140. printf_filtered("\t-f <file> Merge <file> into the device tree\n");
  141. if (verbose) { printf_filtered("\n"); }
  142. printf_filtered("\t-h -? -H give more detailed usage\n");
  143. if (verbose) { printf_filtered("\n"); }
  144. printf_filtered("\t-m <model> Specify the processor to model (604)\n");
  145. if (verbose) {
  146. printf_filtered("\t Selects the processor to use when\n");
  147. printf_filtered("\t modeling execution units. Includes:\n");
  148. printf_filtered("\t 604, 603 and 603e\n");
  149. printf_filtered("\n"); }
  150. printf_filtered("\t-n <nr-smp> Specify the number of processors in SMP simulations\n");
  151. if (verbose) {
  152. printf_filtered("\t Specifies the number of processors that are\n");
  153. printf_filtered("\t to be modeled in a symetric multi-processor (SMP)\n");
  154. printf_filtered("\t simulation\n");
  155. printf_filtered("\n"); }
  156. printf_filtered("\t-o <dev-spec> Add device <dev-spec> to the device tree\n");
  157. if (verbose) { printf_filtered("\n"); }
  158. printf_filtered("\t-r <ram-size> Set RAM size in bytes (OEA environments)\n");
  159. if (verbose) { printf_filtered("\n"); }
  160. printf_filtered("\t-t [!]<trace> Enable (disable) <trace> option\n");
  161. if (verbose) { printf_filtered("\n"); }
  162. printf_filtered("\n");
  163. trace_usage(verbose);
  164. device_usage(verbose);
  165. if (verbose > 1) {
  166. printf_filtered("\n");
  167. print_options();
  168. }
  169. if (kind == SIM_OPEN_STANDALONE)
  170. {
  171. if (REPORT_BUGS_TO[0])
  172. printf ("Report bugs to %s\n", REPORT_BUGS_TO);
  173. exit (help ? 0 : 1);
  174. }
  175. }
  176. /* Test "string" for containing a string of digits that form a number
  177. between "min" and "max". The return value is the number or "err". */
  178. static
  179. int is_num(const char *string, int min, int max, int err)
  180. {
  181. int result = 0;
  182. for ( ; *string; ++string)
  183. {
  184. if (!isdigit(*string))
  185. {
  186. result = err;
  187. break;
  188. }
  189. result = result * 10 + (*string - '0');
  190. }
  191. if (result < min || result > max)
  192. result = err;
  193. return result;
  194. }
  195. INLINE_PSIM\
  196. (char * const *)
  197. psim_options(device *root,
  198. char * const *argv,
  199. SIM_OPEN_KIND kind)
  200. {
  201. device *current = root;
  202. int argp;
  203. if (argv == NULL)
  204. return NULL;
  205. argp = 0;
  206. while (argv[argp] != NULL && argv[argp][0] == '-') {
  207. const char *p = argv[argp] + 1;
  208. const char *param;
  209. while (*p != '\0') {
  210. switch (*p) {
  211. default:
  212. printf_filtered ("Invalid Option: %s\n", argv[argp]);
  213. psim_usage (0, 0, kind);
  214. return NULL;
  215. case 'c':
  216. param = find_arg("Missing <count> option for -c (max-iterations)\n", &argp, argv);
  217. tree_parse(root, "/openprom/options/max-iterations %s", param);
  218. break;
  219. case 'e':
  220. param = find_arg("Missing <emul> option for -e (os-emul)\n", &argp, argv);
  221. tree_parse(root, "/openprom/options/os-emul %s", param);
  222. break;
  223. case 'E':
  224. /* endian spec, ignored for now */
  225. param = find_arg("Missing <endian> option for -E (target-endian)\n", &argp, argv);
  226. if (strcmp (param, "big") == 0)
  227. tree_parse (root, "/options/little-endian? false");
  228. else if (strcmp (param, "little") == 0)
  229. tree_parse (root, "/options/little-endian? true");
  230. else
  231. {
  232. printf_filtered ("Invalid <endian> option for -E (target-endian)\n");
  233. psim_usage (0, 0, kind);
  234. return NULL;
  235. }
  236. break;
  237. case 'f':
  238. param = find_arg("Missing <file> option for -f\n", &argp, argv);
  239. psim_merge_device_file(root, param);
  240. break;
  241. case 'h':
  242. case '?':
  243. psim_usage (1, 1, kind);
  244. return NULL;
  245. case 'H':
  246. psim_usage (2, 1, kind);
  247. return NULL;
  248. case 'i':
  249. if (isdigit(p[1])) {
  250. tree_parse(root, "/openprom/trace/print-info %c", p[1]);
  251. p++;
  252. }
  253. else {
  254. tree_parse(root, "/openprom/trace/print-info 1");
  255. }
  256. break;
  257. case 'I':
  258. tree_parse(root, "/openprom/trace/print-info 2");
  259. tree_parse(root, "/openprom/options/model-issue %d",
  260. MODEL_ISSUE_PROCESS);
  261. break;
  262. case 'm':
  263. param = find_arg("Missing <model> option for -m (model)\n", &argp, argv);
  264. tree_parse(root, "/openprom/options/model \"%s", param);
  265. break;
  266. case 'n':
  267. param = find_arg("Missing <nr-smp> option for -n (smp)\n", &argp, argv);
  268. tree_parse(root, "/openprom/options/smp %s", param);
  269. break;
  270. case 'o':
  271. param = find_arg("Missing <dev-spec> option for -o\n", &argp, argv);
  272. if (memcmp(param, "mpc860c0", 8) == 0)
  273. {
  274. if (param[8] == '\0')
  275. tree_parse(root, "/options/mpc860c0 5");
  276. else if (param[8] == '=' && is_num(param+9, 1, 10, 0))
  277. {
  278. tree_parse(root, "/options/mpc860c0 %s", param+9);
  279. }
  280. else error("Invalid mpc860c0 option for -o\n");
  281. }
  282. else
  283. current = tree_parse(current, "%s", param);
  284. break;
  285. case 'r':
  286. param = find_arg("Missing <ram-size> option for -r (oea-memory-size)\n", &argp, argv);
  287. tree_parse(root, "/openprom/options/oea-memory-size %s",
  288. param);
  289. break;
  290. case 't':
  291. param = find_arg("Missing <trace> option for -t (trace/*)\n", &argp, argv);
  292. if (param[0] == '!')
  293. tree_parse(root, "/openprom/trace/%s 0", param+1);
  294. else
  295. tree_parse(root, "/openprom/trace/%s 1", param);
  296. break;
  297. case '-':
  298. /* it's a long option of the form --optionname=optionvalue.
  299. Such options can be passed through if we are invoked by
  300. gdb. */
  301. if (strstr(argv[argp], "architecture") != NULL) {
  302. /* we must consume the argument here, so that we get out
  303. of the loop. */
  304. p = argv[argp] + strlen(argv[argp]) - 1;
  305. printf_filtered("Warning - architecture parameter ignored\n");
  306. }
  307. else if (strcmp (argv[argp], "--help") == 0)
  308. {
  309. psim_usage (0, 1, kind);
  310. return NULL;
  311. }
  312. else if (strncmp (argv[argp], "--sysroot=",
  313. sizeof ("--sysroot=") - 1) == 0)
  314. /* Ignore this option. */
  315. p = argv[argp] + strlen(argv[argp]) - 1;
  316. else if (strcmp (argv[argp], "--version") == 0)
  317. {
  318. extern const char version[];
  319. printf ("GNU simulator %s%s\n", PKGVERSION, version);
  320. if (kind == SIM_OPEN_STANDALONE)
  321. exit (0);
  322. else
  323. return NULL;
  324. }
  325. else
  326. {
  327. printf_filtered ("Invalid option: %s\n", argv[argp]);
  328. psim_usage (0, 0, kind);
  329. return NULL;
  330. }
  331. break;
  332. }
  333. p += 1;
  334. }
  335. argp += 1;
  336. }
  337. /* force the trace node to process its options now *before* the tree
  338. initialization occures */
  339. device_ioctl(tree_find_device(root, "/openprom/trace"),
  340. NULL, 0,
  341. device_ioctl_set_trace);
  342. {
  343. void semantic_init(device* root);
  344. semantic_init(root);
  345. }
  346. /* return where the options end */
  347. return argv + argp;
  348. }
  349. INLINE_PSIM\
  350. (void)
  351. psim_command(device *root,
  352. char * const *argv)
  353. {
  354. int argp = 0;
  355. if (argv[argp] == NULL) {
  356. return;
  357. }
  358. else if (strcmp(argv[argp], "trace") == 0) {
  359. const char *opt = find_arg("Missing <trace> option", &argp, argv);
  360. if (opt[0] == '!')
  361. trace_option(opt + 1, 0);
  362. else
  363. trace_option(opt, 1);
  364. }
  365. else if (strcmp(*argv, "change-media") == 0) {
  366. const char *device = find_arg("Missing device name", &argp, argv);
  367. const char *media = argv[++argp];
  368. device_ioctl(tree_find_device(root, device), NULL, 0,
  369. device_ioctl_change_media, media);
  370. }
  371. else {
  372. printf_filtered("Unknown PSIM command %s, try\n", argv[argp]);
  373. printf_filtered(" trace <trace-option>\n");
  374. printf_filtered(" change-media <device> [ <new-image> ]\n");
  375. }
  376. }
  377. /* create the simulator proper from the device tree and executable */
  378. INLINE_PSIM\
  379. (psim *)
  380. psim_create(const char *file_name,
  381. device *root)
  382. {
  383. int cpu_nr;
  384. const char *env;
  385. psim *system;
  386. os_emul *os_emulation;
  387. int nr_cpus;
  388. /* given this partially populated device tree, os_emul_create() uses
  389. it and file_name to determine the selected emulation and hence
  390. further populate the tree with any other required nodes. */
  391. os_emulation = os_emul_create(file_name, root);
  392. if (os_emulation == NULL)
  393. error("psim: either file %s was not reconized or unreconized or unknown os-emulation type\n", file_name);
  394. /* fill in the missing real number of CPU's */
  395. nr_cpus = tree_find_integer_property(root, "/openprom/options/smp");
  396. if (MAX_NR_PROCESSORS < nr_cpus)
  397. error("target and configured number of cpus conflict\n");
  398. /* fill in the missing TARGET BYTE ORDER information */
  399. current_target_byte_order
  400. = (tree_find_boolean_property(root, "/options/little-endian?")
  401. ? BFD_ENDIAN_LITTLE
  402. : BFD_ENDIAN_BIG);
  403. if (CURRENT_TARGET_BYTE_ORDER != current_target_byte_order)
  404. error("target and configured byte order conflict\n");
  405. /* fill in the missing OEA/VEA information */
  406. env = tree_find_string_property(root, "/openprom/options/env");
  407. current_environment = ((strcmp(env, "user") == 0
  408. || strcmp(env, "uea") == 0)
  409. ? USER_ENVIRONMENT
  410. : (strcmp(env, "virtual") == 0
  411. || strcmp(env, "vea") == 0)
  412. ? VIRTUAL_ENVIRONMENT
  413. : (strcmp(env, "operating") == 0
  414. || strcmp(env, "oea") == 0)
  415. ? OPERATING_ENVIRONMENT
  416. : 0);
  417. if (current_environment == 0)
  418. error("unreconized /options env property\n");
  419. if (CURRENT_ENVIRONMENT != current_environment)
  420. error("target and configured environment conflict\n");
  421. /* fill in the missing ALLIGNMENT information */
  422. current_alignment
  423. = (tree_find_boolean_property(root, "/openprom/options/strict-alignment?")
  424. ? STRICT_ALIGNMENT
  425. : NONSTRICT_ALIGNMENT);
  426. if (CURRENT_ALIGNMENT != current_alignment)
  427. error("target and configured alignment conflict\n");
  428. /* fill in the missing FLOATING POINT information */
  429. current_floating_point
  430. = (tree_find_boolean_property(root, "/openprom/options/floating-point?")
  431. ? HARD_FLOATING_POINT
  432. : SOFT_FLOATING_POINT);
  433. if (CURRENT_FLOATING_POINT != current_floating_point)
  434. error("target and configured floating-point conflict\n");
  435. /* fill in the missing STDIO information */
  436. current_stdio
  437. = (tree_find_boolean_property(root, "/openprom/options/use-stdio?")
  438. ? DO_USE_STDIO
  439. : DONT_USE_STDIO);
  440. if (CURRENT_STDIO != current_stdio)
  441. error("target and configured stdio interface conflict\n");
  442. /* sort out the level of detail for issue modeling */
  443. current_model_issue
  444. = tree_find_integer_property(root, "/openprom/options/model-issue");
  445. if (CURRENT_MODEL_ISSUE != current_model_issue)
  446. error("target and configured model-issue conflict\n");
  447. /* sort out our model architecture - wrong.
  448. FIXME: this should be obtaining the required information from the
  449. device tree via the "/chosen" property "cpu" which is an instance
  450. (ihandle) for the only executing processor. By converting that
  451. ihandle into the corresponding cpu's phandle and then querying
  452. the "name" property, the cpu type can be determined. Ok? */
  453. model_set(tree_find_string_property(root, "/openprom/options/model"));
  454. /* create things */
  455. system = ZALLOC(psim);
  456. system->events = event_queue_create();
  457. system->memory = core_from_device(root);
  458. system->monitor = mon_create();
  459. system->nr_cpus = nr_cpus;
  460. system->os_emulation = os_emulation;
  461. system->devices = root;
  462. /* now all the processors attaching to each their per-cpu information */
  463. for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) {
  464. system->processors[cpu_nr] = cpu_create(system,
  465. system->memory,
  466. mon_cpu(system->monitor,
  467. cpu_nr),
  468. system->os_emulation,
  469. cpu_nr);
  470. }
  471. /* dump out the contents of the device tree */
  472. if (ppc_trace[trace_print_device_tree] || ppc_trace[trace_dump_device_tree])
  473. tree_print(root);
  474. if (ppc_trace[trace_dump_device_tree])
  475. error("");
  476. return system;
  477. }
  478. /* allow the simulation to stop/restart abnormaly */
  479. INLINE_PSIM\
  480. (void)
  481. psim_set_halt_and_restart(psim *system,
  482. void *halt_jmp_buf,
  483. void *restart_jmp_buf)
  484. {
  485. system->path_to_halt = halt_jmp_buf;
  486. system->path_to_restart = restart_jmp_buf;
  487. }
  488. INLINE_PSIM\
  489. (void)
  490. psim_clear_halt_and_restart(psim *system)
  491. {
  492. system->path_to_halt = NULL;
  493. system->path_to_restart = NULL;
  494. }
  495. INLINE_PSIM\
  496. (void)
  497. psim_restart(psim *system,
  498. int current_cpu)
  499. {
  500. ASSERT(current_cpu >= 0 && current_cpu < system->nr_cpus);
  501. ASSERT(system->path_to_restart != NULL);
  502. system->last_cpu = current_cpu;
  503. longjmp(*(jmp_buf*)(system->path_to_restart), current_cpu + 1);
  504. }
  505. static void
  506. cntrl_c_simulation(void *data)
  507. {
  508. psim *system = data;
  509. psim_halt(system,
  510. psim_nr_cpus(system),
  511. was_continuing,
  512. GDB_SIGNAL_INT);
  513. }
  514. INLINE_PSIM\
  515. (void)
  516. psim_stop(psim *system)
  517. {
  518. event_queue_schedule_after_signal(psim_event_queue(system),
  519. 0 /*NOW*/,
  520. cntrl_c_simulation,
  521. system);
  522. }
  523. INLINE_PSIM\
  524. (void)
  525. psim_halt(psim *system,
  526. int current_cpu,
  527. stop_reason reason,
  528. int signal)
  529. {
  530. ASSERT(current_cpu >= 0 && current_cpu <= system->nr_cpus);
  531. ASSERT(system->path_to_halt != NULL);
  532. system->last_cpu = current_cpu;
  533. system->halt_status.reason = reason;
  534. system->halt_status.signal = signal;
  535. if (current_cpu == system->nr_cpus) {
  536. system->halt_status.cpu_nr = 0;
  537. system->halt_status.program_counter =
  538. cpu_get_program_counter(system->processors[0]);
  539. }
  540. else {
  541. system->halt_status.cpu_nr = current_cpu;
  542. system->halt_status.program_counter =
  543. cpu_get_program_counter(system->processors[current_cpu]);
  544. }
  545. longjmp(*(jmp_buf*)(system->path_to_halt), current_cpu + 1);
  546. }
  547. INLINE_PSIM\
  548. (int)
  549. psim_last_cpu(psim *system)
  550. {
  551. return system->last_cpu;
  552. }
  553. INLINE_PSIM\
  554. (int)
  555. psim_nr_cpus(psim *system)
  556. {
  557. return system->nr_cpus;
  558. }
  559. INLINE_PSIM\
  560. (psim_status)
  561. psim_get_status(psim *system)
  562. {
  563. return system->halt_status;
  564. }
  565. INLINE_PSIM\
  566. (cpu *)
  567. psim_cpu(psim *system,
  568. int cpu_nr)
  569. {
  570. if (cpu_nr < 0 || cpu_nr >= system->nr_cpus)
  571. return NULL;
  572. else
  573. return system->processors[cpu_nr];
  574. }
  575. INLINE_PSIM\
  576. (device *)
  577. psim_device(psim *system,
  578. const char *path)
  579. {
  580. return tree_find_device(system->devices, path);
  581. }
  582. INLINE_PSIM\
  583. (event_queue *)
  584. psim_event_queue(psim *system)
  585. {
  586. return system->events;
  587. }
  588. STATIC_INLINE_PSIM\
  589. (void)
  590. psim_max_iterations_exceeded(void *data)
  591. {
  592. psim *system = data;
  593. psim_halt(system,
  594. system->nr_cpus, /* halted during an event */
  595. was_signalled,
  596. -1);
  597. }
  598. INLINE_PSIM\
  599. (void)
  600. psim_init(psim *system)
  601. {
  602. int cpu_nr;
  603. /* scrub the monitor */
  604. mon_init(system->monitor, system->nr_cpus);
  605. /* trash any pending events */
  606. event_queue_init(system->events);
  607. /* if needed, schedule a halt event. FIXME - In the future this
  608. will be replaced by a more generic change to psim_command(). A
  609. new command `schedule NNN halt' being added. */
  610. if (tree_find_property(system->devices, "/openprom/options/max-iterations")) {
  611. event_queue_schedule(system->events,
  612. tree_find_integer_property(system->devices,
  613. "/openprom/options/max-iterations") - 2,
  614. psim_max_iterations_exceeded,
  615. system);
  616. }
  617. /* scrub all the cpus */
  618. for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++)
  619. cpu_init(system->processors[cpu_nr]);
  620. /* init all the devices (which updates the cpus) */
  621. tree_init(system->devices, system);
  622. /* and the emulation (which needs an initialized device tree) */
  623. os_emul_init(system->os_emulation, system->nr_cpus);
  624. /* now sync each cpu against the initialized state of its registers */
  625. for (cpu_nr = 0; cpu_nr < system->nr_cpus; cpu_nr++) {
  626. cpu *processor = system->processors[cpu_nr];
  627. cpu_synchronize_context(processor, cpu_get_program_counter(processor));
  628. cpu_page_tlb_invalidate_all(processor);
  629. }
  630. /* force loop to start with first cpu */
  631. system->last_cpu = -1;
  632. }
  633. INLINE_PSIM\
  634. (void)
  635. psim_stack(psim *system,
  636. char * const *argv,
  637. char * const *envp)
  638. {
  639. /* pass the stack device the argv/envp and let it work out what to
  640. do with it */
  641. device *stack_device = tree_find_device(system->devices,
  642. "/openprom/init/stack");
  643. if (stack_device != (device*)0) {
  644. unsigned_word stack_pointer;
  645. ASSERT (psim_read_register(system, 0, &stack_pointer, "sp",
  646. cooked_transfer) > 0);
  647. device_ioctl(stack_device,
  648. NULL, /*cpu*/
  649. 0, /*cia*/
  650. device_ioctl_create_stack,
  651. stack_pointer,
  652. argv,
  653. envp);
  654. }
  655. }
  656. /* SIMULATE INSTRUCTIONS, various different ways of achieving the same
  657. thing */
  658. INLINE_PSIM\
  659. (void)
  660. psim_step(psim *system)
  661. {
  662. volatile int keep_running = 0;
  663. idecode_run_until_stop(system, &keep_running,
  664. system->events, system->processors, system->nr_cpus);
  665. }
  666. INLINE_PSIM\
  667. (void)
  668. psim_run(psim *system)
  669. {
  670. idecode_run(system,
  671. system->events, system->processors, system->nr_cpus);
  672. }
  673. /* storage manipulation functions */
  674. INLINE_PSIM\
  675. (int)
  676. psim_read_register(psim *system,
  677. int which_cpu,
  678. void *buf,
  679. const char reg[],
  680. transfer_mode mode)
  681. {
  682. register_descriptions description;
  683. char *cooked_buf;
  684. cpu *processor;
  685. /* find our processor */
  686. if (which_cpu == MAX_NR_PROCESSORS) {
  687. if (system->last_cpu == system->nr_cpus
  688. || system->last_cpu == -1)
  689. which_cpu = 0;
  690. else
  691. which_cpu = system->last_cpu;
  692. }
  693. ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  694. processor = system->processors[which_cpu];
  695. /* find the register description */
  696. description = register_description(reg);
  697. if (description.type == reg_invalid)
  698. return 0;
  699. cooked_buf = alloca (description.size);
  700. /* get the cooked value */
  701. switch (description.type) {
  702. case reg_gpr:
  703. *(gpreg*)cooked_buf = cpu_registers(processor)->gpr[description.index];
  704. break;
  705. case reg_spr:
  706. *(spreg*)cooked_buf = cpu_registers(processor)->spr[description.index];
  707. break;
  708. case reg_sr:
  709. *(sreg*)cooked_buf = cpu_registers(processor)->sr[description.index];
  710. break;
  711. case reg_fpr:
  712. *(fpreg*)cooked_buf = cpu_registers(processor)->fpr[description.index];
  713. break;
  714. case reg_pc:
  715. *(unsigned_word*)cooked_buf = cpu_get_program_counter(processor);
  716. break;
  717. case reg_cr:
  718. *(creg*)cooked_buf = cpu_registers(processor)->cr;
  719. break;
  720. case reg_msr:
  721. *(msreg*)cooked_buf = cpu_registers(processor)->msr;
  722. break;
  723. case reg_fpscr:
  724. *(fpscreg*)cooked_buf = cpu_registers(processor)->fpscr;
  725. break;
  726. case reg_insns:
  727. *(unsigned_word*)cooked_buf = mon_get_number_of_insns(system->monitor,
  728. which_cpu);
  729. break;
  730. case reg_stalls:
  731. if (cpu_model(processor) == NULL)
  732. error("$stalls only valid if processor unit model enabled (-I)\n");
  733. *(unsigned_word*)cooked_buf = model_get_number_of_stalls(cpu_model(processor));
  734. break;
  735. case reg_cycles:
  736. if (cpu_model(processor) == NULL)
  737. error("$cycles only valid if processor unit model enabled (-I)\n");
  738. *(unsigned_word*)cooked_buf = model_get_number_of_cycles(cpu_model(processor));
  739. break;
  740. #ifdef WITH_ALTIVEC
  741. case reg_vr:
  742. *(vreg*)cooked_buf = cpu_registers(processor)->altivec.vr[description.index];
  743. break;
  744. case reg_vscr:
  745. *(vscreg*)cooked_buf = cpu_registers(processor)->altivec.vscr;
  746. break;
  747. #endif
  748. #ifdef WITH_E500
  749. case reg_gprh:
  750. *(gpreg*)cooked_buf = cpu_registers(processor)->e500.gprh[description.index];
  751. break;
  752. case reg_evr:
  753. *(uint64_t*)cooked_buf = EVR(description.index);
  754. break;
  755. case reg_acc:
  756. *(accreg*)cooked_buf = cpu_registers(processor)->e500.acc;
  757. break;
  758. #endif
  759. default:
  760. printf_filtered("psim_read_register(processor=%p,buf=%p,reg=%s) %s\n",
  761. processor, buf, reg, "read of this register unimplemented");
  762. break;
  763. }
  764. /* the PSIM internal values are in host order. To fetch raw data,
  765. they need to be converted into target order and then returned */
  766. if (mode == raw_transfer) {
  767. /* FIXME - assumes that all registers are simple integers */
  768. switch (description.size) {
  769. case 1:
  770. *(unsigned_1*)buf = H2T_1(*(unsigned_1*)cooked_buf);
  771. break;
  772. case 2:
  773. *(unsigned_2*)buf = H2T_2(*(unsigned_2*)cooked_buf);
  774. break;
  775. case 4:
  776. *(unsigned_4*)buf = H2T_4(*(unsigned_4*)cooked_buf);
  777. break;
  778. case 8:
  779. *(unsigned_8*)buf = H2T_8(*(unsigned_8*)cooked_buf);
  780. break;
  781. #ifdef WITH_ALTIVEC
  782. case 16:
  783. if (HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
  784. {
  785. union { vreg v; unsigned_8 d[2]; } h, t;
  786. memcpy(&h.v/*dest*/, cooked_buf/*src*/, description.size);
  787. { _SWAP_8(t.d[0] =, h.d[1]); }
  788. { _SWAP_8(t.d[1] =, h.d[0]); }
  789. memcpy(buf/*dest*/, &t/*src*/, description.size);
  790. break;
  791. }
  792. else
  793. memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
  794. break;
  795. #endif
  796. }
  797. }
  798. else {
  799. memcpy(buf/*dest*/, cooked_buf/*src*/, description.size);
  800. }
  801. return description.size;
  802. }
  803. INLINE_PSIM\
  804. (int)
  805. psim_write_register(psim *system,
  806. int which_cpu,
  807. const void *buf,
  808. const char reg[],
  809. transfer_mode mode)
  810. {
  811. cpu *processor;
  812. register_descriptions description;
  813. char *cooked_buf;
  814. /* find our processor */
  815. if (which_cpu == MAX_NR_PROCESSORS) {
  816. if (system->last_cpu == system->nr_cpus
  817. || system->last_cpu == -1)
  818. which_cpu = 0;
  819. else
  820. which_cpu = system->last_cpu;
  821. }
  822. /* find the description of the register */
  823. description = register_description(reg);
  824. if (description.type == reg_invalid)
  825. return 0;
  826. cooked_buf = alloca (description.size);
  827. if (which_cpu == -1) {
  828. int i;
  829. for (i = 0; i < system->nr_cpus; i++)
  830. psim_write_register(system, i, buf, reg, mode);
  831. return description.size;
  832. }
  833. ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  834. processor = system->processors[which_cpu];
  835. /* If the data is comming in raw (target order), need to cook it
  836. into host order before putting it into PSIM's internal structures */
  837. if (mode == raw_transfer) {
  838. switch (description.size) {
  839. case 1:
  840. *(unsigned_1*)cooked_buf = T2H_1(*(unsigned_1*)buf);
  841. break;
  842. case 2:
  843. *(unsigned_2*)cooked_buf = T2H_2(*(unsigned_2*)buf);
  844. break;
  845. case 4:
  846. *(unsigned_4*)cooked_buf = T2H_4(*(unsigned_4*)buf);
  847. break;
  848. case 8:
  849. *(unsigned_8*)cooked_buf = T2H_8(*(unsigned_8*)buf);
  850. break;
  851. #ifdef WITH_ALTIVEC
  852. case 16:
  853. if (HOST_BYTE_ORDER != CURRENT_TARGET_BYTE_ORDER)
  854. {
  855. union { vreg v; unsigned_8 d[2]; } h, t;
  856. memcpy(&t.v/*dest*/, buf/*src*/, description.size);
  857. { _SWAP_8(h.d[0] =, t.d[1]); }
  858. { _SWAP_8(h.d[1] =, t.d[0]); }
  859. memcpy(cooked_buf/*dest*/, &h/*src*/, description.size);
  860. break;
  861. }
  862. else
  863. memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
  864. #endif
  865. }
  866. }
  867. else {
  868. memcpy(cooked_buf/*dest*/, buf/*src*/, description.size);
  869. }
  870. /* put the cooked value into the register */
  871. switch (description.type) {
  872. case reg_gpr:
  873. cpu_registers(processor)->gpr[description.index] = *(gpreg*)cooked_buf;
  874. break;
  875. case reg_fpr:
  876. cpu_registers(processor)->fpr[description.index] = *(fpreg*)cooked_buf;
  877. break;
  878. case reg_pc:
  879. cpu_set_program_counter(processor, *(unsigned_word*)cooked_buf);
  880. break;
  881. case reg_spr:
  882. cpu_registers(processor)->spr[description.index] = *(spreg*)cooked_buf;
  883. break;
  884. case reg_sr:
  885. cpu_registers(processor)->sr[description.index] = *(sreg*)cooked_buf;
  886. break;
  887. case reg_cr:
  888. cpu_registers(processor)->cr = *(creg*)cooked_buf;
  889. break;
  890. case reg_msr:
  891. cpu_registers(processor)->msr = *(msreg*)cooked_buf;
  892. break;
  893. case reg_fpscr:
  894. cpu_registers(processor)->fpscr = *(fpscreg*)cooked_buf;
  895. break;
  896. #ifdef WITH_E500
  897. case reg_gprh:
  898. cpu_registers(processor)->e500.gprh[description.index] = *(gpreg*)cooked_buf;
  899. break;
  900. case reg_evr:
  901. {
  902. uint64_t v;
  903. v = *(uint64_t*)cooked_buf;
  904. cpu_registers(processor)->e500.gprh[description.index] = v >> 32;
  905. cpu_registers(processor)->gpr[description.index] = v;
  906. break;
  907. }
  908. case reg_acc:
  909. cpu_registers(processor)->e500.acc = *(accreg*)cooked_buf;
  910. break;
  911. #endif
  912. #ifdef WITH_ALTIVEC
  913. case reg_vr:
  914. cpu_registers(processor)->altivec.vr[description.index] = *(vreg*)cooked_buf;
  915. break;
  916. case reg_vscr:
  917. cpu_registers(processor)->altivec.vscr = *(vscreg*)cooked_buf;
  918. break;
  919. #endif
  920. default:
  921. printf_filtered("psim_write_register(processor=%p,cooked_buf=%p,reg=%s) %s\n",
  922. processor, cooked_buf, reg,
  923. "read of this register unimplemented");
  924. break;
  925. }
  926. return description.size;
  927. }
  928. INLINE_PSIM\
  929. (unsigned)
  930. psim_read_memory(psim *system,
  931. int which_cpu,
  932. void *buffer,
  933. unsigned_word vaddr,
  934. unsigned nr_bytes)
  935. {
  936. cpu *processor;
  937. if (which_cpu == MAX_NR_PROCESSORS) {
  938. if (system->last_cpu == system->nr_cpus
  939. || system->last_cpu == -1)
  940. which_cpu = 0;
  941. else
  942. which_cpu = system->last_cpu;
  943. }
  944. processor = system->processors[which_cpu];
  945. return vm_data_map_read_buffer(cpu_data_map(processor),
  946. buffer, vaddr, nr_bytes,
  947. NULL, -1);
  948. }
  949. INLINE_PSIM\
  950. (unsigned)
  951. psim_write_memory(psim *system,
  952. int which_cpu,
  953. const void *buffer,
  954. unsigned_word vaddr,
  955. unsigned nr_bytes,
  956. int violate_read_only_section)
  957. {
  958. cpu *processor;
  959. if (which_cpu == MAX_NR_PROCESSORS) {
  960. if (system->last_cpu == system->nr_cpus
  961. || system->last_cpu == -1)
  962. which_cpu = 0;
  963. else
  964. which_cpu = system->last_cpu;
  965. }
  966. ASSERT(which_cpu >= 0 && which_cpu < system->nr_cpus);
  967. processor = system->processors[which_cpu];
  968. return vm_data_map_write_buffer(cpu_data_map(processor),
  969. buffer, vaddr, nr_bytes, 1/*violate-read-only*/,
  970. NULL, -1);
  971. }
  972. INLINE_PSIM\
  973. (void)
  974. psim_print_info(psim *system,
  975. int verbose)
  976. {
  977. mon_print_info(system, system->monitor, verbose);
  978. }
  979. /* Merge a device tree and a device file. */
  980. INLINE_PSIM\
  981. (void)
  982. psim_merge_device_file(device *root,
  983. const char *file_name)
  984. {
  985. FILE *description;
  986. int line_nr;
  987. char device_path[1000];
  988. device *current;
  989. /* try opening the file */
  990. description = fopen(file_name, "r");
  991. if (description == NULL) {
  992. perror(file_name);
  993. error("Invalid file %s specified", file_name);
  994. }
  995. line_nr = 0;
  996. current = root;
  997. while (fgets(device_path, sizeof(device_path), description)) {
  998. char *device;
  999. /* check that the full line was read */
  1000. if (strchr(device_path, '\n') == NULL) {
  1001. fclose(description);
  1002. error("%s:%d: line to long - %s",
  1003. file_name, line_nr, device_path);
  1004. }
  1005. else
  1006. *strchr(device_path, '\n') = '\0';
  1007. line_nr++;
  1008. /* skip comments ("#" or ";") and blank lines lines */
  1009. for (device = device_path;
  1010. *device != '\0' && isspace(*device);
  1011. device++);
  1012. if (device[0] == '#'
  1013. || device[0] == ';'
  1014. || device[0] == '\0')
  1015. continue;
  1016. /* merge any appended lines */
  1017. while (device_path[strlen(device_path) - 1] == '\\') {
  1018. int curlen = strlen(device_path) - 1;
  1019. /* zap \ */
  1020. device_path[curlen] = '\0';
  1021. /* append the next line */
  1022. if (!fgets(device_path + curlen, sizeof(device_path) - curlen, description)) {
  1023. fclose(description);
  1024. error("%s:%s: unexpected eof in line continuation - %s",
  1025. file_name, line_nr, device_path);
  1026. }
  1027. if (strchr(device_path, '\n') == NULL) {
  1028. fclose(description);
  1029. error("%s:%d: line to long - %s",
  1030. file_name, line_nr, device_path);
  1031. }
  1032. else
  1033. *strchr(device_path, '\n') = '\0';
  1034. line_nr++;
  1035. }
  1036. /* parse this line */
  1037. current = tree_parse(current, "%s", device);
  1038. }
  1039. fclose(description);
  1040. }
  1041. #endif /* _PSIM_C_ */