reg.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /* reg.c --- register set model for RX simulator.
  2. Copyright (C) 2005-2022 Free Software Foundation, Inc.
  3. Contributed by Red Hat, Inc.
  4. This file is part of the GNU simulators.
  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. /* This must come before any other includes. */
  16. #include "defs.h"
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "cpu.h"
  21. #include "bfd.h"
  22. #include "trace.h"
  23. int verbose = 0;
  24. int trace = 0;
  25. int enable_counting = 0;
  26. int rx_in_gdb = 1;
  27. int rx_flagmask;
  28. int rx_flagand;
  29. int rx_flagor;
  30. int rx_big_endian;
  31. regs_type regs;
  32. int step_result;
  33. unsigned int heapbottom = 0;
  34. unsigned int heaptop = 0;
  35. char *reg_names[] = {
  36. /* general registers */
  37. "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  38. "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
  39. /* control register */
  40. "psw", "pc", "usp", "fpsw", "RES", "RES", "RES", "RES",
  41. "bpsw", "bpc", "isp", "fintv", "intb", "RES", "RES", "RES",
  42. "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES",
  43. "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES",
  44. "temp", "acc", "acchi", "accmi", "acclo"
  45. };
  46. unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff };
  47. unsigned int b2signbit[] = { 0, (1 << 7), (1 << 15), (1 << 24), (1 << 31) };
  48. int b2maxsigned[] = { 0, 0x7f, 0x7fff, 0x7fffff, 0x7fffffff };
  49. int b2minsigned[] = { 0, -128, -32768, -8388608, -2147483647 - 1 };
  50. static regs_type oldregs;
  51. void
  52. init_regs (void)
  53. {
  54. memset (&regs, 0, sizeof (regs));
  55. memset (&oldregs, 0, sizeof (oldregs));
  56. #ifdef CYCLE_ACCURATE
  57. regs.rt = -1;
  58. oldregs.rt = -1;
  59. #endif
  60. }
  61. static unsigned int
  62. get_reg_i (int id)
  63. {
  64. if (id == 0)
  65. return regs.r_psw & FLAGBIT_U ? regs.r_usp : regs.r_isp;
  66. if (id >= 1 && id <= 15)
  67. return regs.r[id];
  68. switch (id)
  69. {
  70. case psw:
  71. return regs.r_psw;
  72. case fpsw:
  73. return regs.r_fpsw;
  74. case isp:
  75. return regs.r_isp;
  76. case usp:
  77. return regs.r_usp;
  78. case bpc:
  79. return regs.r_bpc;
  80. case bpsw:
  81. return regs.r_bpsw;
  82. case fintv:
  83. return regs.r_fintv;
  84. case intb:
  85. return regs.r_intb;
  86. case pc:
  87. return regs.r_pc;
  88. case r_temp_idx:
  89. return regs.r_temp;
  90. case acchi:
  91. return (SI)(regs.r_acc >> 32);
  92. case accmi:
  93. return (SI)(regs.r_acc >> 16);
  94. case acclo:
  95. return (SI)regs.r_acc;
  96. }
  97. abort();
  98. }
  99. unsigned int
  100. get_reg (int id)
  101. {
  102. unsigned int rv = get_reg_i (id);
  103. if (trace > ((id != pc && id != sp) ? 0 : 1))
  104. printf ("get_reg (%s) = %08x\n", reg_names[id], rv);
  105. return rv;
  106. }
  107. static unsigned long long
  108. get_reg64_i (int id)
  109. {
  110. switch (id)
  111. {
  112. case acc64:
  113. return regs.r_acc;
  114. default:
  115. abort ();
  116. }
  117. }
  118. unsigned long long
  119. get_reg64 (int id)
  120. {
  121. unsigned long long rv = get_reg64_i (id);
  122. if (trace > ((id != pc && id != sp) ? 0 : 1))
  123. printf ("get_reg (%s) = %016llx\n", reg_names[id], rv);
  124. return rv;
  125. }
  126. static int highest_sp = 0, lowest_sp = 0xffffff;
  127. void
  128. stack_heap_stats (void)
  129. {
  130. if (heapbottom < heaptop)
  131. printf ("heap: %08x - %08x (%d bytes)\n", heapbottom, heaptop,
  132. heaptop - heapbottom);
  133. if (lowest_sp < highest_sp)
  134. printf ("stack: %08x - %08x (%d bytes)\n", lowest_sp, highest_sp,
  135. highest_sp - lowest_sp);
  136. }
  137. void
  138. put_reg (int id, unsigned int v)
  139. {
  140. if (trace > ((id != pc) ? 0 : 1))
  141. printf ("put_reg (%s) = %08x\n", reg_names[id], v);
  142. switch (id)
  143. {
  144. case psw:
  145. regs.r_psw = v;
  146. break;
  147. case fpsw:
  148. {
  149. SI anded;
  150. /* This is an odd one - The Cx flags are AND'd, and the FS flag
  151. is synthetic. */
  152. anded = regs.r_fpsw & v;
  153. anded |= ~ FPSWBITS_CMASK;
  154. regs.r_fpsw = v & anded;
  155. if (regs.r_fpsw & FPSWBITS_FMASK)
  156. regs.r_fpsw |= FPSWBITS_FSUM;
  157. else
  158. regs.r_fpsw &= ~FPSWBITS_FSUM;
  159. }
  160. break;
  161. case isp:
  162. regs.r_isp = v;
  163. break;
  164. case usp:
  165. regs.r_usp = v;
  166. break;
  167. case bpc:
  168. regs.r_bpc = v;
  169. break;
  170. case bpsw:
  171. regs.r_bpsw = v;
  172. break;
  173. case fintv:
  174. regs.r_fintv = v;
  175. break;
  176. case intb:
  177. regs.r_intb = v;
  178. break;
  179. case pc:
  180. regs.r_pc = v;
  181. break;
  182. case acchi:
  183. regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32);
  184. break;
  185. case accmi:
  186. regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16);
  187. break;
  188. case acclo:
  189. regs.r_acc = (regs.r_acc & ~0xffffffffULL) | ((DI)v);
  190. break;
  191. case 0: /* Stack pointer is "in" R0. */
  192. {
  193. if (v < heaptop)
  194. {
  195. unsigned int line;
  196. const char * dummy;
  197. const char * fname = NULL;
  198. sim_get_current_source_location (& dummy, & fname, &line);
  199. /* The setjmp and longjmp functions play tricks with the stack pointer. */
  200. if (fname == NULL
  201. || (strcmp (fname, "_setjmp") != 0
  202. && strcmp (fname, "_longjmp") != 0))
  203. {
  204. printf ("collision in %s: pc %08x heap %08x stack %08x\n",
  205. fname, (unsigned int) regs.r_pc, heaptop, v);
  206. exit (1);
  207. }
  208. }
  209. else
  210. {
  211. if (v < lowest_sp)
  212. lowest_sp = v;
  213. if (v > highest_sp)
  214. highest_sp = v;
  215. }
  216. if (regs.r_psw & FLAGBIT_U)
  217. regs.r_usp = v;
  218. else
  219. regs.r_isp = v;
  220. break;
  221. }
  222. default:
  223. if (id >= 1 && id <= 15)
  224. regs.r[id] = v;
  225. else
  226. abort ();
  227. }
  228. }
  229. void
  230. put_reg64 (int id, unsigned long long v)
  231. {
  232. if (trace > ((id != pc) ? 0 : 1))
  233. printf ("put_reg (%s) = %016llx\n", reg_names[id], v);
  234. switch (id)
  235. {
  236. case acc64:
  237. regs.r_acc = v;
  238. break;
  239. default:
  240. abort ();
  241. }
  242. }
  243. int
  244. condition_true (int cond_id)
  245. {
  246. int f;
  247. static const char *cond_name[] = {
  248. "Z",
  249. "!Z",
  250. "C",
  251. "!C",
  252. "C&!Z",
  253. "!(C&!Z)",
  254. "!S",
  255. "S",
  256. "!(S^O)",
  257. "S^O",
  258. "!((S^O)|Z)",
  259. "(S^O)|Z",
  260. "O",
  261. "!O",
  262. "always",
  263. "never"
  264. };
  265. switch (cond_id & 15)
  266. {
  267. case 0:
  268. f = FLAG_Z;
  269. break; /* EQ/Z */
  270. case 1:
  271. f = !FLAG_Z;
  272. break; /* NE/NZ */
  273. case 2:
  274. f = FLAG_C;
  275. break; /* GEU/C */
  276. case 3:
  277. f = !FLAG_C;
  278. break; /* LTU/NC */
  279. case 4:
  280. f = FLAG_C & !FLAG_Z;
  281. break; /* GTU */
  282. case 5:
  283. f = !(FLAG_C & !FLAG_Z);
  284. break; /* LEU */
  285. case 6:
  286. f = !FLAG_S;
  287. break; /* PZ */
  288. case 7:
  289. f = FLAG_S;
  290. break; /* N */
  291. case 8:
  292. f = !(FLAG_S ^ FLAG_O);
  293. break; /* GE */
  294. case 9:
  295. f = FLAG_S ^ FLAG_O;
  296. break; /* LT */
  297. case 10:
  298. f = !((FLAG_S ^ FLAG_O) | FLAG_Z);
  299. break; /* GT */
  300. case 11:
  301. f = (FLAG_S ^ FLAG_O) | FLAG_Z;
  302. break; /* LE */
  303. case 12:
  304. f = FLAG_O;
  305. break; /* O */
  306. case 13:
  307. f = !FLAG_O;
  308. break; /* NO */
  309. case 14:
  310. f = 1; /* always */
  311. break;
  312. default:
  313. f = 0; /* never */
  314. break;
  315. }
  316. if (trace && ((cond_id & 15) != 14))
  317. printf ("cond[%d] %s = %s\n", cond_id, cond_name[cond_id & 15],
  318. f ? "true" : "false");
  319. return f;
  320. }
  321. void
  322. set_flags (int mask, int newbits)
  323. {
  324. regs.r_psw &= rx_flagand;
  325. regs.r_psw |= rx_flagor;
  326. regs.r_psw |= (newbits & mask & rx_flagmask);
  327. if (trace)
  328. {
  329. int i;
  330. printf ("flags now \033[32m %d", (int)((regs.r_psw >> 24) & 7));
  331. for (i = 17; i >= 0; i--)
  332. if (0x3000f & (1 << i))
  333. {
  334. if (regs.r_psw & (1 << i))
  335. putchar ("CZSO------------IU"[i]);
  336. else
  337. putchar ('-');
  338. }
  339. printf ("\033[0m\n");
  340. }
  341. }
  342. void
  343. set_oszc (long long value, int b, int c)
  344. {
  345. unsigned int mask = b2mask[b];
  346. int f = 0;
  347. if (c)
  348. f |= FLAGBIT_C;
  349. if ((value & mask) == 0)
  350. f |= FLAGBIT_Z;
  351. if (value & b2signbit[b])
  352. f |= FLAGBIT_S;
  353. if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
  354. f |= FLAGBIT_O;
  355. set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O | FLAGBIT_C, f);
  356. }
  357. void
  358. set_szc (long long value, int b, int c)
  359. {
  360. unsigned int mask = b2mask[b];
  361. int f = 0;
  362. if (c)
  363. f |= FLAGBIT_C;
  364. if ((value & mask) == 0)
  365. f |= FLAGBIT_Z;
  366. if (value & b2signbit[b])
  367. f |= FLAGBIT_S;
  368. set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_C, f);
  369. }
  370. void
  371. set_osz (long long value, int b)
  372. {
  373. unsigned int mask = b2mask[b];
  374. int f = 0;
  375. if ((value & mask) == 0)
  376. f |= FLAGBIT_Z;
  377. if (value & b2signbit[b])
  378. f |= FLAGBIT_S;
  379. if ((value > b2maxsigned[b]) || (value < b2minsigned[b]))
  380. f |= FLAGBIT_O;
  381. set_flags (FLAGBIT_Z | FLAGBIT_S | FLAGBIT_O, f);
  382. }
  383. void
  384. set_sz (long long value, int b)
  385. {
  386. unsigned int mask = b2mask[b];
  387. int f = 0;
  388. if ((value & mask) == 0)
  389. f |= FLAGBIT_Z;
  390. if (value & b2signbit[b])
  391. f |= FLAGBIT_S;
  392. set_flags (FLAGBIT_Z | FLAGBIT_S, f);
  393. }
  394. void
  395. set_zc (int z, int c)
  396. {
  397. set_flags (FLAGBIT_C | FLAGBIT_Z,
  398. (c ? FLAGBIT_C : 0) | (z ? FLAGBIT_Z : 0));
  399. }
  400. void
  401. set_c (int c)
  402. {
  403. set_flags (FLAGBIT_C, c ? FLAGBIT_C : 0);
  404. }
  405. static char *
  406. psw2str(int rpsw)
  407. {
  408. static char buf[10];
  409. char *bp = buf;
  410. int i, ipl;
  411. ipl = (rpsw & FLAGBITS_IPL) >> FLAGSHIFT_IPL;
  412. if (ipl > 9)
  413. {
  414. *bp++ = (ipl / 10) + '0';
  415. ipl %= 10;
  416. }
  417. *bp++ = ipl + '0';
  418. for (i = 20; i >= 0; i--)
  419. if (0x13000f & (1 << i))
  420. {
  421. if (rpsw & (1 << i))
  422. *bp++ = "CZSO------------IU--P"[i];
  423. else
  424. *bp++ = '-';
  425. }
  426. *bp = 0;
  427. return buf;
  428. }
  429. static char *
  430. fpsw2str(int rpsw)
  431. {
  432. static char buf[100];
  433. char *bp = buf;
  434. int i; /* ---+---+---+---+---+---+---+---+ */
  435. const char s1[] = "FFFFFF-----------EEEEE-DCCCCCCRR";
  436. const char s2[] = "SXUZOV-----------XUZOV-NEXUZOV01";
  437. const char rm[4][3] = { "RC", "RZ", "RP", "RN" };
  438. for (i = 31; i >= 0; i--)
  439. if (0xfc007dfc & (1 << i))
  440. {
  441. if (rpsw & (1 << i))
  442. {
  443. if (bp > buf)
  444. *bp++ = '.';
  445. *bp++ = s1[31-i];
  446. *bp++ = s2[31-i];
  447. }
  448. }
  449. if (bp > buf)
  450. *bp++ = '.';
  451. strcpy (bp, rm[rpsw&3]);
  452. return buf;
  453. }
  454. #define TRC(f,n) \
  455. if (oldregs.f != regs.f) \
  456. { \
  457. if (tag) { printf ("%s", tag); tag = 0; } \
  458. printf(" %s %08x:%08x", n, \
  459. (unsigned int)oldregs.f, \
  460. (unsigned int)regs.f); \
  461. oldregs.f = regs.f; \
  462. }
  463. void
  464. trace_register_changes (void)
  465. {
  466. char *tag = "\033[36mREGS:";
  467. int i;
  468. if (!trace)
  469. return;
  470. for (i=1; i<16; i++)
  471. TRC (r[i], reg_names[i]);
  472. TRC (r_intb, "intb");
  473. TRC (r_usp, "usp");
  474. TRC (r_isp, "isp");
  475. if (oldregs.r_psw != regs.r_psw)
  476. {
  477. if (tag) { printf ("%s", tag); tag = 0; }
  478. printf(" psw %s:", psw2str(oldregs.r_psw));
  479. printf("%s", psw2str(regs.r_psw));
  480. oldregs.r_psw = regs.r_psw;
  481. }
  482. if (oldregs.r_fpsw != regs.r_fpsw)
  483. {
  484. if (tag) { printf ("%s", tag); tag = 0; }
  485. printf(" fpsw %s:", fpsw2str(oldregs.r_fpsw));
  486. printf("%s", fpsw2str(regs.r_fpsw));
  487. oldregs.r_fpsw = regs.r_fpsw;
  488. }
  489. if (oldregs.r_acc != regs.r_acc)
  490. {
  491. if (tag) { printf ("%s", tag); tag = 0; }
  492. printf(" acc %016" PRIx64 ":", oldregs.r_acc);
  493. printf("%016" PRIx64, regs.r_acc);
  494. oldregs.r_acc = regs.r_acc;
  495. }
  496. if (tag == 0)
  497. printf ("\033[0m\n");
  498. }