ms_reg.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. /* catch register messages. BEWARE: code uses plain printf's (fprint's)
  2. * to generate code. This is not compatible with the usual procedure
  3. * used in the EM_table
  4. */
  5. #define CODE_EXPANDER
  6. #include <em.h>
  7. #include <em_reg.h>
  8. #include <em_mes.h>
  9. #include <stb.h>
  10. #include "mach.h"
  11. #include "push_pop.h"
  12. #include <stdio.h>
  13. #define MAX_NR_REGS 12
  14. #define MAX_NR_FLTS MAX_NR_FLT_REGS /* depends on using float or doubles */
  15. #define RM_OFFSET 0
  16. #define RM_SIZE 1
  17. #define RM_TYPE 2
  18. #define RM_COUNT 3
  19. typedef struct reg_info {
  20. int offset;
  21. int size; /* 4 or 8 */
  22. int pri;
  23. reg_t reg, reg2; /* reg2 used for doubles only */
  24. } reg_info;
  25. static reg_info reg_dat[MAX_NR_REGS], flt_dat[MAX_NR_FLTS];
  26. static int current_reg_mes[RM_COUNT+4];
  27. static int in_reg_mes = 0; /* boolean */
  28. static int reg_mes_nr;
  29. static int db_mes = 0;
  30. static int db_kind = 0;
  31. static int db_str = 0;
  32. static int db_nul = 0; /* boolean */
  33. static int worst_reg_pri, worst_flt_pri; /* reset by C_prolog (to some large number) */
  34. static int nr_reg_vars, nr_flt_vars; /* dito (both to 0) */
  35. init_reg_man()
  36. {
  37. worst_reg_pri = worst_flt_pri = (unsigned)-1/2;
  38. nr_reg_vars = nr_flt_vars = 0;
  39. }
  40. static reg_t my_alloc_reg(pri,loc)
  41. int pri, *loc;
  42. {
  43. reg_t S1;
  44. int i;
  45. if ((S1 = alloc_reg_var()) == NULL)
  46. if (current_reg_mes[RM_COUNT] > worst_reg_pri) {
  47. for (i = 0; i < nr_reg_vars; i++)
  48. if (reg_dat[i].pri <= worst_reg_pri) {
  49. *loc = i;
  50. S1 = reg_dat[i].reg;
  51. break;
  52. }
  53. worst_reg_pri = (unsigned)-1/2;
  54. for (i = 0; i < nr_reg_vars; i++)
  55. if (reg_dat[i].pri <= worst_reg_pri)
  56. worst_reg_pri = reg_dat[i].pri;
  57. } else
  58. return NULL; /* SORRY, FULL HOUSE! */
  59. else
  60. *loc = nr_reg_vars++;
  61. return S1;
  62. }
  63. static reg_t my_alloc_double(pri,loc,r2)
  64. int pri, *loc;
  65. reg_t *r2;
  66. /* implementation note: my_alloc_double only reclaims other doubles
  67. * when a better candidate is given. It never reclaims floats, even if
  68. * the current double is a mich better candidate.
  69. */
  70. {
  71. reg_t S1;
  72. int i;
  73. if ((S1 = alloc_double_var(r2)) == NULL)
  74. if (current_reg_mes[RM_COUNT] > worst_flt_pri) {
  75. for (i = 0; i < nr_flt_vars; i++)
  76. if (flt_dat[i].pri <= worst_flt_pri &&
  77. flt_dat[i].size == EM_DSIZE) {
  78. *loc = i;
  79. S1 = flt_dat[i].reg;
  80. *r2 = flt_dat[i].reg2;
  81. break;
  82. }
  83. worst_flt_pri = (unsigned)-1/2;
  84. for (i = 0; i < nr_flt_vars; i++)
  85. if (flt_dat[i].pri < worst_flt_pri)
  86. worst_flt_pri = flt_dat[i].pri;
  87. } else
  88. return NULL; /* SORRY, FULL HOUSE! */
  89. else
  90. *loc = nr_flt_vars++;
  91. return S1;
  92. }
  93. static reg_t my_alloc_float(pri,loc)
  94. int pri, *loc;
  95. /* just as for my_alloc_double, my_alloc_float never reclaims a double,
  96. * even though this me be useful and easy. Sorry.
  97. */
  98. {
  99. reg_t S1;
  100. int i;
  101. if ((S1 = alloc_float_var()) == NULL)
  102. if (current_reg_mes[RM_COUNT] > worst_flt_pri) {
  103. for (i = 0; i < nr_flt_vars; i++)
  104. if (flt_dat[i].pri <= worst_flt_pri &&
  105. flt_dat[i].size == EM_WSIZE) {
  106. *loc = i;
  107. S1 = flt_dat[i].reg;
  108. break;
  109. }
  110. worst_flt_pri = (unsigned)-1/2;
  111. for (i = 0; i < nr_flt_vars; i++)
  112. if (flt_dat[i].pri <= worst_flt_pri)
  113. worst_flt_pri = flt_dat[i].pri;
  114. } else
  115. return NULL; /* SORRY, FULL HOUSE! */
  116. else
  117. *loc = nr_flt_vars++;
  118. return S1;
  119. }
  120. free_all_reg_vars()
  121. {
  122. int i;
  123. for (i = 0; i < nr_reg_vars; i++)
  124. free_reg(reg_dat[i].reg);
  125. for (i = 0; i < nr_flt_vars; i++)
  126. switch (flt_dat[i].size) {
  127. case EM_WSIZE: free_reg(flt_dat[i].reg); break;
  128. case EM_DSIZE: free_double_reg(flt_dat[i].reg); break;
  129. }
  130. check_cache();
  131. }
  132. alloc_all_reg_vars()
  133. {
  134. int i;
  135. for (i = 0; i < nr_reg_vars; i++)
  136. forced_alloc_reg(reg_dat[i].reg);
  137. for (i = 0; i < nr_flt_vars; i++)
  138. switch (flt_dat[i].size) {
  139. case EM_WSIZE: forced_alloc_reg(flt_dat[i].reg); break;
  140. case EM_DSIZE:
  141. forced_alloc_reg(flt_dat[i].reg);
  142. forced_alloc_reg(flt_dat[i].reg2);
  143. break;
  144. }
  145. check_cache();
  146. }
  147. static params_to_regs() /* copy required parameters to registers */
  148. {
  149. int i, j;
  150. for (i = 0; i < nr_flt_vars; i++)
  151. if (flt_dat[i].offset >= 4092) {
  152. fprint(codefile, "set %d, %%l2\n",
  153. flt_dat[i].offset);
  154. fprint(codefile, "ld [%%l1+%%l2], %s\n",
  155. flt_dat[i].reg);
  156. if (flt_dat[i].size == EM_DSIZE) {
  157. fprint(codefile, "set %d, %%l2\n",
  158. flt_dat[i].offset+4);
  159. fprint(codefile, "ld [%%l1+%%l2], %s\n",
  160. flt_dat[i].reg2);
  161. }
  162. }
  163. else if (flt_dat[i].offset > 0)
  164. {
  165. fprint(codefile, "ld [%%l1+%d], %s\n",
  166. flt_dat[i].offset, flt_dat[i].reg);
  167. if (flt_dat[i].size == EM_DSIZE)
  168. fprint(codefile, "ld [%%l1+%d], %s\n",
  169. flt_dat[i].offset + 4, flt_dat[i].reg2);
  170. }
  171. for (i = 0; i < nr_reg_vars; i++)
  172. if (reg_dat[i].offset >= 4096) {
  173. fprint(codefile, "set %d, %s\n",
  174. reg_dat[i].offset, reg_dat[i].reg);
  175. fprint(codefile, "ld [%%l1+%s], %s\n",
  176. reg_dat[i].reg, reg_dat[i].reg);
  177. }
  178. else if (reg_dat[i].offset > 0)
  179. fprint(codefile, "ld [%%l1+%d], %s\n",
  180. reg_dat[i].offset, reg_dat[i].reg);
  181. }
  182. static cmp_flt_dat(e1, e2)
  183. reg_info *e1, *e2;
  184. {
  185. return (e1->offset - e2->offset);
  186. }
  187. static int even(s)
  188. char *s;
  189. {
  190. int l = strlen(s);
  191. /* Assume ASCII, where even-numbered characters (0,2,4,6,8) are even. */
  192. return ! (s[l-1] & 1);
  193. }
  194. static save_float_regs()
  195. {
  196. int i;
  197. int offset;
  198. qsort(flt_dat, nr_flt_vars, sizeof(flt_dat[0]), cmp_flt_dat);
  199. for (i = 0, offset= 0; i < nr_flt_vars; i++, offset += 8)
  200. if ((i+1 < nr_flt_vars &&
  201. flt_dat[i].offset == flt_dat[i+1].offset-4 &&
  202. even(flt_dat[i].reg) &&
  203. flt_dat[i].size == EM_FSIZE &&
  204. flt_dat[i+1].size == EM_FSIZE)
  205. || (flt_dat[i].size == EM_DSIZE)) {
  206. fprint(codefile, "std %s, [%%fp + %d]\n",
  207. flt_dat[i].reg, FLTSAV_OFFSET + offset);
  208. if (flt_dat[i].size != EM_DSIZE)
  209. ++i;
  210. } else
  211. fprint(codefile, "st %s, [%%fp + %d]\n",
  212. flt_dat[i].reg, FLTSAV_OFFSET + offset);
  213. }
  214. load_float_regs()
  215. {
  216. int i;
  217. int offset;
  218. for (i = 0, offset= 0; i < nr_flt_vars; i++, offset += 8)
  219. if ((i+1 < nr_flt_vars &&
  220. flt_dat[i].offset == flt_dat[i+1].offset-4 &&
  221. even(flt_dat[i].reg) &&
  222. flt_dat[i].size == EM_FSIZE &&
  223. flt_dat[i+1].size == EM_FSIZE)
  224. || (flt_dat[i].size == EM_DSIZE)) {
  225. fprint(codefile, "ldd [%%fp + %d], %s\n",
  226. FLTSAV_OFFSET + offset, flt_dat[i].reg);
  227. if (flt_dat[i].size != EM_DSIZE)
  228. ++i;
  229. } else
  230. fprint(codefile, "ld [%%fp + %d], %s\n",
  231. FLTSAV_OFFSET + offset, flt_dat[i].reg);
  232. }
  233. void
  234. C_mes_begin( ms)
  235. int ms;
  236. {
  237. #ifdef __solaris__
  238. static int inits;
  239. #endif
  240. reg_mes_nr = 0;
  241. in_reg_mes = (ms == ms_reg);
  242. if (ms == ms_gto) {
  243. free_all_reg_vars();
  244. nr_reg_vars = 0; nr_flt_vars = 0;
  245. fprint(codefile, "ta 3\n");
  246. }
  247. db_mes = (ms == ms_stb || ms == ms_std) ? ms : 0;
  248. #ifdef __solaris__
  249. if (db_mes && ! inits) {
  250. fprint(codefile, ".pushsection \".text\"\nBtext.text:\n.popsection\n");
  251. fprint(codefile, ".pushsection \".data\"\nBdata.data:\n.popsection\n");
  252. fprint(codefile, ".pushsection \".bss\"\nBbss.bss:\n.popsection\n");
  253. inits = 1;
  254. }
  255. #endif
  256. }
  257. static dump_reg_tabs();
  258. #ifdef __solaris__
  259. extern char *B_procnam;
  260. #endif
  261. void
  262. C_mes_end()
  263. {
  264. int pos;
  265. reg_t S1, S2;
  266. if (db_mes) {
  267. db_nul = 0;
  268. #ifdef __solaris__
  269. if (db_mes == ms_std) {
  270. if (db_str == 2) {
  271. fprint(codefile, ",1f\n1:\n");
  272. }
  273. else {
  274. fprint(codefile, ",1f-%s\n1:\n", B_procnam);
  275. }
  276. }
  277. #else
  278. if (db_mes == ms_std && db_str == 2) fprint(codefile,",1f\n1:\n");
  279. #endif
  280. else fprint(codefile, "\n");
  281. db_str = 0;
  282. db_mes = 0;
  283. db_kind = 0;
  284. }
  285. if (!in_reg_mes) /* end of some other mes */
  286. return;
  287. if (reg_mes_nr == 0) { /* end of reg_mes's */
  288. save_float_regs();
  289. params_to_regs();
  290. if (debug)
  291. dump_reg_tabs(codefile);
  292. return;
  293. }
  294. if (current_reg_mes[RM_COUNT] == 0) /* never used, so ignore */
  295. return;
  296. if (current_reg_mes[RM_OFFSET] >= 0)
  297. current_reg_mes[RM_OFFSET] += EM_BSIZE;
  298. if (debug)
  299. fprint(codefile, "\t\t! Got reg_mes: %d %d %d %d\n",
  300. current_reg_mes[0], current_reg_mes[1],
  301. current_reg_mes[2], current_reg_mes[3]);
  302. if (current_reg_mes[RM_TYPE] == reg_float) {
  303. switch(current_reg_mes[RM_SIZE]) {
  304. case EM_WSIZE :
  305. if ((S1 = my_alloc_float(current_reg_mes[RM_COUNT], &pos))
  306. == NULL)
  307. return;
  308. break;
  309. case EM_DSIZE:
  310. if ((S1 = my_alloc_double(current_reg_mes[RM_COUNT], &pos, &S2))
  311. == NULL)
  312. return;
  313. flt_dat[pos].reg2 = S2;
  314. default: break;
  315. }
  316. flt_dat[pos].offset = current_reg_mes[RM_OFFSET];
  317. flt_dat[pos].size = current_reg_mes[RM_SIZE];
  318. flt_dat[pos].pri = current_reg_mes[RM_COUNT];
  319. flt_dat[pos].reg = S1;
  320. } else {
  321. if (current_reg_mes[RM_SIZE] != EM_WSIZE)
  322. return; /* IGNORE THESE */
  323. if ((S1 = my_alloc_reg(current_reg_mes[RM_COUNT], &pos)) == NULL)
  324. return; /* SORRY, FULL HOUSE! */
  325. reg_dat[pos].offset = current_reg_mes[RM_OFFSET];
  326. reg_dat[pos].size = current_reg_mes[RM_SIZE];
  327. reg_dat[pos].pri = current_reg_mes[RM_COUNT];
  328. reg_dat[pos].reg = S1;
  329. }
  330. }
  331. extern int __gdb_flag;
  332. void
  333. C_cst( l)
  334. arith l;
  335. {
  336. static int correct_offset;
  337. if (db_mes) {
  338. if (! db_kind) db_kind = l;
  339. if (! db_str) {
  340. switchseg( SEGTXT);
  341. if (l == N_SLINE && ! __gdb_flag) {
  342. flush_cache();
  343. #ifdef __solaris__
  344. fprint(codefile, "call $__uX_LiB\nnop\n");
  345. #else
  346. fprint(codefile, "call ___uX_LiB\nnop\n");
  347. #endif
  348. }
  349. #ifdef __solaris__
  350. fprint(codefile, ".stabn 0x%lx,0", (long) l);
  351. #else
  352. if (db_mes == ms_std) {
  353. fprint(codefile, ".stabd 0x%lx,0", (long) l);
  354. }
  355. else fprint(codefile, ".stabn 0x%lx,0", (long) l);
  356. #endif
  357. db_str = 1;
  358. db_nul = 1;
  359. }
  360. else {
  361. if (correct_offset++ == -1) {
  362. l += EM_BSIZE;
  363. }
  364. fprint(codefile, ",0x%lx", (long) l);
  365. }
  366. if (! db_nul) {
  367. correct_offset = 0;
  368. if (l == N_PSYM && __gdb_flag) {
  369. correct_offset = -2;
  370. }
  371. fprint(codefile, ",0");
  372. db_nul = 1;
  373. }
  374. }
  375. if (in_reg_mes)
  376. current_reg_mes[reg_mes_nr++] = l;
  377. }
  378. void
  379. C_scon(s, l)
  380. register char *s;
  381. register arith l;
  382. {
  383. if (db_mes) {
  384. fprint(codefile, ".stabs \"");
  385. while (--l) {
  386. register int c = *s++;
  387. if (isprint(c) && c != '"' && c != '\\')
  388. fprint(codefile, "%c", c);
  389. else
  390. fprint(codefile, "\\%03o", c);
  391. }
  392. fprint(codefile, "\"");
  393. db_str = 2;
  394. }
  395. }
  396. void
  397. C_dlb(l, off)
  398. label l;
  399. arith off;
  400. {
  401. if (db_mes) {
  402. fprint(codefile,",");
  403. fprint(codefile, DLB_FMT, (long) l);
  404. if (off) fprint(codefile,"+%ld", (long) off);
  405. #ifdef __solaris__
  406. switch(db_kind) {
  407. case N_LCSYM:
  408. fprint(codefile, "-Bbss.bss");
  409. break;
  410. case N_STSYM:
  411. fprint(codefile, "-Bdata.data");
  412. break;
  413. }
  414. #endif
  415. }
  416. }
  417. void
  418. C_dnam(l, off)
  419. char *l;
  420. arith off;
  421. {
  422. if (db_mes) {
  423. fprint(codefile,",");
  424. fprint(codefile, DNAM_FMT, l);
  425. if (off) fprint(codefile,"+%ld", (long) off);
  426. #ifdef __solaris__
  427. switch(db_kind) {
  428. case N_LCSYM:
  429. fprint(codefile, "-Bbss.bss");
  430. break;
  431. case N_STSYM:
  432. fprint(codefile, "-Bdata.data");
  433. break;
  434. }
  435. #endif
  436. }
  437. }
  438. extern int B_procno;
  439. void
  440. C_ilb(l)
  441. label l;
  442. {
  443. if (db_mes) {
  444. fprint(codefile,",");
  445. fprint(codefile, ILB_FMT, B_procno, (long)l);
  446. #ifdef __solaris__
  447. fprint(codefile, "-Btext.text");
  448. #endif
  449. }
  450. }
  451. void
  452. C_pnam(s)
  453. char *s;
  454. {
  455. if (db_mes) {
  456. fprint(codefile,",");
  457. fprint(codefile, NAME_FMT, s);
  458. #ifdef __solaris__
  459. fprint(codefile, "-Btext.text");
  460. #endif
  461. }
  462. }
  463. static
  464. dump_reg_tabs(stream)
  465. FILE *stream;
  466. {
  467. int i;
  468. fprint(stream, "!offset\tsize\tname (%d regvars)\n", nr_reg_vars);
  469. for (i = 0; i < nr_reg_vars; i++)
  470. fprint(stream, "! %d\t%d\t%s\n", reg_dat[i].offset, reg_dat[i].size,
  471. reg_dat[i].reg);
  472. fprint(stream, "!offset\tsize\tname (%d fltvars)\n", nr_flt_vars);
  473. for (i = 0; i < nr_flt_vars; i++)
  474. fprint(stream, "! %d\t%d\t%s\n", flt_dat[i].offset, flt_dat[i].size,
  475. flt_dat[i].reg);
  476. }
  477. reg_t find_local(offset, reg2) /* WARNING: no size checking here! */
  478. int offset;
  479. reg_t *reg2;
  480. {
  481. int i;
  482. if (reg2)
  483. *reg2 = NULL;
  484. for (i = 0; i < nr_reg_vars; i++)
  485. if (reg_dat[i].offset == offset)
  486. return reg_dat[i].reg;
  487. for (i = 0; i < nr_flt_vars; i++)
  488. if (flt_dat[i].offset == offset) {
  489. if (flt_dat[i].size == EM_DSIZE)
  490. if (reg2)
  491. *reg2 = flt_dat[i].reg2;
  492. return flt_dat[i].reg;
  493. }
  494. return NULL;
  495. }