cache.c.x 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300
  1. /* cache.c */
  2. #include <stdio.h>
  3. #include <assert.h>
  4. #include "mach.h"
  5. #ifdef __STDC__
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #else
  9. extern char *malloc();
  10. extern char *strcpy();
  11. #endif
  12. #define free_reg_num(i) if (1) { assert(reg[i].inuse > 0); reg[i].inuse--; if (debug) fprintf(stderr,"free_reg(%s)\n", regnam[i]); } else
  13. #define POP1 cache_need(1);
  14. #define POP2 { --tos; assert(c_count); --c_count; }
  15. static int indent_count = 0;
  16. #define enter(x) indent_count++;
  17. #define indent() { int i = indent_count; while (i--) putc('\t', stderr); }
  18. #define leave(x) indent_count--;
  19. /* procedures:
  20. const13(int) boolean proc
  21. init_cache() mandatory
  22. free_reg(reg_t)
  23. forced_alloc_reg(reg_t)
  24. soft_alloc_reg(reg_t)
  25. change_reg(reg_t) used when reg on stack has changed
  26. type_of_tos() bit-field representation of ext/reg/cst
  27. inc_tos(int) tos->cst += n
  28. push_const(int)
  29. push_reg(reg_t)
  30. push_ext(char *)
  31. flush_cache() after branches and labels
  32. cache_read(int) read-ahead. optimization only
  33. dump_cache(File *) debug info: show current stack
  34. pop_nop() remove element from cache
  35. reg_t alloc_reg()
  36. reg_t pop_reg()
  37. reg_t pop_reg_c13(char*)
  38. arith pop_const(char *)
  39. arith top_const()
  40. alloc_float, alloc_double, free_double,
  41. pop_float, pop_double, push_float, push_double
  42. */
  43. typedef struct regdat_t {
  44. int inuse; /* free == 0, otherwise #owners */
  45. } regdat_t;
  46. /*
  47. typedef struct cache_elt {
  48. reg_t reg, reg2;
  49. char *ext;
  50. arith cst;
  51. } cache_elt;
  52. */
  53. #define REG_NUM(r) (((char(*)[8])(r))-regnam)
  54. static char regnam[][8] = {
  55. /*x*/ "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
  56. /*x*/ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i6", "%i7",
  57. /*x*/ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
  58. /*x*/ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o6", "%o7",
  59. /*x*/ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
  60. /*x*/ "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
  61. /*x*/ "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
  62. /*x*/ "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31"
  63. };
  64. reg_t reg_g0, reg_g1, reg_g2, reg_g3, reg_g4, reg_g5, reg_g6, reg_g7;
  65. reg_t reg_i0, reg_i1, reg_i2, reg_i3, reg_i4, reg_i5, reg_i6, reg_i7;
  66. reg_t reg_l0, reg_l1, reg_l2, reg_l3, reg_l4, reg_l5, reg_l6, reg_l7;
  67. reg_t reg_o0, reg_o1, reg_o2, reg_o3, reg_o4, reg_o5, reg_o6, reg_o7;
  68. reg_t reg_f0;
  69. reg_t reg_sp, reg_lb, reg_gap;
  70. reg_t reg_tmp, reg_lin, reg_fil;
  71. static struct regdat_t reg[NR_REGS];
  72. #define POP_SIZE 1 /* maybe >1 (read-ahead cache) or explicit?! */
  73. #define CACHE_SIZE 32 /* ? */
  74. #define LO_GLOB 0
  75. #define HI_GLOB 7
  76. #define LO_IN 8
  77. #define HI_IN 15
  78. #define LO_LOC 16
  79. #define HI_LOC 23
  80. #define LO_OUT 24
  81. #define HI_OUT 31
  82. #define LO_FLOAT 32
  83. #define HI_FLOAT 63
  84. const13(x)
  85. {
  86. return (x < 4096 && x >= -4096);
  87. }
  88. static struct cache_elt cache[CACHE_SIZE], *tos = 0;
  89. static int c_count = 0;
  90. static const_str_t s;
  91. static void panic(s)
  92. char *s;
  93. {
  94. printf("PANIC: %s\n", s);
  95. exit(1);
  96. }
  97. void init_cache()
  98. {
  99. int i;
  100. for (i = 0; i < NR_REGS; i++)
  101. reg[i].inuse = 0;
  102. reg_g0 = regnam[000];
  103. reg_g1 = regnam[001];
  104. reg_g2 = regnam[002];
  105. reg_g3 = regnam[003];
  106. reg_g4 = regnam[004];
  107. reg_g5 = regnam[005];
  108. reg_g6 = regnam[006];
  109. reg_g7 = regnam[007];
  110. reg_i0 = regnam[010];
  111. reg_i1 = regnam[011];
  112. reg_i2 = regnam[012];
  113. reg_i3 = regnam[013];
  114. reg_i4 = regnam[014];
  115. reg_i5 = regnam[015];
  116. reg_i6 = regnam[016];
  117. reg_i7 = regnam[017];
  118. reg_l0 = regnam[020];
  119. reg_l1 = regnam[021];
  120. reg_l2 = regnam[022];
  121. reg_l3 = regnam[023];
  122. reg_l4 = regnam[024];
  123. reg_l5 = regnam[025];
  124. reg_l6 = regnam[026];
  125. reg_l7 = regnam[027];
  126. reg_o0 = regnam[030];
  127. reg_o1 = regnam[031];
  128. reg_o2 = regnam[032];
  129. reg_o3 = regnam[033];
  130. reg_o4 = regnam[034];
  131. reg_o5 = regnam[035];
  132. reg_o6 = regnam[036];
  133. reg_o7 = regnam[037];
  134. reg_f0 = regnam[040];
  135. reg_sp = reg_l0;
  136. reg_lb = reg_l1;
  137. reg_gap = reg_g4;
  138. reg_tmp = reg_o7;
  139. forced_alloc_reg(reg_g0); /* can not be used as a reg */
  140. forced_alloc_reg(reg_o6);
  141. forced_alloc_reg(reg_o7);
  142. forced_alloc_reg(reg_i6);
  143. forced_alloc_reg(reg_i7);
  144. }
  145. static void flush_part_cache(n,r,f,d)
  146. int n,r,f,d;
  147. {
  148. /* free at least n entries, r integer registers, f float regs and d double regs
  149. */
  150. int i, ready;
  151. int rn, j;
  152. const_str_t i_str, e_str, n_str;
  153. char *ext, R1, R2;
  154. reg_t rh, rt;
  155. enter("flush_part_cache");
  156. for (i = 0; i < c_count; i++)
  157. {
  158. if (i >= n && !r && !f && !d)
  159. break;
  160. if (cache[i].reg != reg_g0)
  161. {
  162. rn= REG_NUM(cache[i].reg);
  163. free_reg_num(rn);
  164. if (!reg[rn].inuse)
  165. if (rn<LO_FLOAT)
  166. {
  167. if (r)
  168. r--;
  169. }
  170. else
  171. {
  172. if (d && (((rn & 1) &&
  173. !reg[rn-1].inuse) ||
  174. (!(rn & 1) && !reg[rn+1].inuse)))
  175. d--;
  176. if (f)
  177. f--;
  178. }
  179. }
  180. if (cache[i].reg2 != reg_g0)
  181. {
  182. rn= REG_NUM(cache[i].reg2);
  183. free_reg_num(rn);
  184. if (!reg[rn].inuse)
  185. if (rn<LO_FLOAT)
  186. {
  187. if (r)
  188. r--;
  189. }
  190. else
  191. {
  192. if (d && (((rn & 1) &&
  193. !reg[rn-1].inuse) ||
  194. (!(rn & 1) && !reg[rn+1].inuse)))
  195. d--;
  196. if (f)
  197. f--;
  198. }
  199. }
  200. }
  201. if (r || f || d)
  202. panic ("can't free enough registers");
  203. j = i;
  204. if (i)
  205. {
  206. sprint (i_str, "%d", 4*i);
  207. "dec $i_str, $reg_sp";
  208. while (i--)
  209. {
  210. sprint(i_str, "%d", 4*(j-1-i));
  211. if (cache[i].ext)
  212. {
  213. ext= cache[i].ext;
  214. sprint (e_str, "%d", cache[i].cst);
  215. "set $ext+$e_str, $reg_tmp";
  216. "st $reg_tmp, [$reg_sp+$i_str]";
  217. free(ext);
  218. }
  219. else
  220. {
  221. if (cache[i].reg2 != reg_g0)
  222. {
  223. rt = cache[i].reg;
  224. rh = cache[i].reg2;
  225. "add $rt, $rh, $reg_tmp";
  226. cache[i].reg = reg_tmp;
  227. cache[i].reg2 = reg_g0;
  228. }
  229. if (!const13(cache[i].cst))
  230. {
  231. sprint(n_str, "%d",
  232. cache[i].cst);
  233. "sethi %hi($n_str), $reg_tmp";
  234. if (cache[i].reg != reg_g0)
  235. {
  236. rt = cache[i].reg;
  237. "add $reg_tmp, $rt, $reg_tmp";
  238. }
  239. rh= reg_tmp;
  240. cache[i].cst &= 0x3ff;
  241. }
  242. else {
  243. rh= cache[i].reg;
  244. }
  245. if (cache[i].cst)
  246. {
  247. sprint(n_str, "%d", cache[i].cst);
  248. "add $rh, $n_str, $reg_tmp";
  249. rh= reg_tmp;
  250. }
  251. "st $rh, [$reg_sp+$i_str]";
  252. }
  253. }
  254. for (i= j; i < c_count; i++)
  255. cache[i-j]= cache[i];
  256. c_count -= j;
  257. tos= &cache[c_count-1];
  258. }
  259. leave("flush_part_cache");
  260. }
  261. reg_t alloc_reg()
  262. {
  263. int i;
  264. reg_t res = NULL;
  265. enter("alloc_reg");
  266. for (i = LO_GLOB+1 /* SPEED-HACK */; i <= HI_GLOB; i++) {
  267. if (reg[i].inuse)
  268. continue;
  269. reg[i].inuse = 1; /* allocate */
  270. res = regnam[i];
  271. break;
  272. }
  273. if (!res)
  274. for (i = LO_IN; i <= HI_IN; i++) {
  275. if (reg[i].inuse)
  276. continue;
  277. reg[i].inuse = 1; /* allocate */
  278. res = regnam[i];
  279. break;
  280. }
  281. if (!res)
  282. for (i = LO_LOC; i <= HI_LOC; i++) {
  283. if (reg[i].inuse)
  284. continue;
  285. reg[i].inuse = 1; /* allocate */
  286. res = regnam[i];
  287. break;
  288. }
  289. if (!res)
  290. for (i = LO_OUT; i <= HI_OUT; i++) {
  291. if (reg[i].inuse)
  292. continue;
  293. reg[i].inuse = 1; /* allocate */
  294. res = regnam[i];
  295. break;
  296. }
  297. if (!res) {
  298. flush_part_cache(c_count/2,1,0,0);
  299. res = alloc_reg();
  300. }
  301. if (debug) { indent(); fprintf(stderr,"alloc_reg() = %s\n", res ? regnam[i] : "NULL"); }
  302. leave("alloc_reg");
  303. return res;
  304. }
  305. reg_t alloc_float()
  306. {
  307. int i;
  308. reg_t res = NULL;
  309. enter("alloc_float");
  310. for (i = LO_FLOAT+15; i >= LO_FLOAT; i--) {
  311. if (reg[i].inuse)
  312. continue;
  313. reg[i].inuse = 1; /* allocate */
  314. res = regnam[i];
  315. break;
  316. }
  317. if (!res) {
  318. flush_part_cache(c_count/2,0,1,0);
  319. res = alloc_float();
  320. }
  321. if (debug) { indent(); fprintf(stderr,"alloc_float() = %s\n", res ? regnam[i] : "NULL"); }
  322. leave("alloc_float");
  323. return res;
  324. }
  325. reg_t alloc_double(sub_reg)
  326. reg_t *sub_reg;
  327. {
  328. int i;
  329. reg_t res = NULL;
  330. enter("alloc_double");
  331. for (i = LO_FLOAT+14; i >= LO_FLOAT; i -= 2) {
  332. if (reg[i].inuse || reg[i+1].inuse)
  333. continue;
  334. reg[i].inuse = 1; /* allocate */
  335. reg[i+1].inuse = 1; /* allocate */
  336. if (debug) { indent(); fprintf(stderr,"alloc_double() = %s\n", regnam[i]); }
  337. if (sub_reg)
  338. *sub_reg= regnam[i+1];
  339. res = regnam[i];
  340. break;
  341. }
  342. if (!res) {
  343. flush_part_cache(c_count/2,0,0,1);
  344. res = alloc_double(sub_reg);
  345. }
  346. if (debug) { indent(); fprintf(stderr,"alloc_double() = %s\n", res ? regnam[i] : "NULL"); }
  347. leave("alloc_double");
  348. return res;
  349. }
  350. reg_t alloc_reg_var() /* ins and locals only */
  351. {
  352. int i;
  353. reg_t res = NULL;
  354. enter("alloc_reg_var");
  355. for (i = LO_LOC +2 /* SPEED-HACK */; i <= HI_LOC; i++) {
  356. if (reg[i].inuse)
  357. continue;
  358. reg[i].inuse = 1; /* allocate */
  359. res = regnam[i];
  360. break;
  361. }
  362. if (!res)
  363. for (i = LO_IN; i <= HI_IN; i++) {
  364. if (reg[i].inuse)
  365. continue;
  366. reg[i].inuse = 1; /* allocate */
  367. res = regnam[i];
  368. break;
  369. }
  370. if (debug) { indent(); fprintf(stderr,"alloc_reg_var() = %s\n", res ? regnam[i] : "NULL"); }
  371. leave("alloc_reg_var");
  372. return res;
  373. }
  374. reg_t alloc_float_var()
  375. {
  376. int i;
  377. reg_t res = NULL;
  378. enter("alloc_float_var");
  379. for (i= LO_FLOAT+16; i<= HI_FLOAT; i++)
  380. {
  381. if (reg[i].inuse)
  382. continue;
  383. reg[i].inuse = 1; /* allocate */
  384. res = regnam[i];
  385. break;
  386. }
  387. if (debug) { indent(); fprintf(stderr,"alloc_reg_var() = %s\n", res ? regnam[i] : "NULL"); }
  388. leave("alloc_float_var");
  389. return res;
  390. }
  391. reg_t alloc_double_var(sub_reg)
  392. reg_t *sub_reg;
  393. {
  394. int i;
  395. reg_t res = NULL;
  396. enter("alloc_double_var");
  397. for (i = LO_FLOAT+16; i < HI_FLOAT; i += 2) {
  398. if (reg[i].inuse || reg[i+1].inuse)
  399. continue;
  400. reg[i].inuse = 1; /* allocate */
  401. reg[i+1].inuse = 1; /* allocate */
  402. if (debug) { indent(); fprintf(stderr,"alloc_double_var() = %s\n", regnam[i]); }
  403. if (sub_reg)
  404. *sub_reg= regnam[i+1];
  405. res = regnam[i];
  406. break;
  407. }
  408. if (debug) { indent(); fprintf(stderr,"alloc_double_var() = %s\n", res? regnam[i] : "NULL"); }
  409. leave("alloc_double_var");
  410. return res;
  411. }
  412. void free_reg(i)
  413. reg_t i;
  414. {
  415. int r;
  416. enter("free_reg");
  417. if (i != 0 && i != reg_g0) {
  418. r = REG_NUM(i);
  419. assert(0 <= r && r <= NR_REGS);
  420. assert(reg[r].inuse > 0); /* "freeing unused register" */
  421. reg[r].inuse--;
  422. }
  423. if (debug) { indent(); fprintf(stderr,"free_reg(%s)\n", i); }
  424. leave("free_reg");
  425. }
  426. void free_double_reg(i)
  427. reg_t i;
  428. {
  429. int rn;
  430. enter("free_double_reg");
  431. rn= REG_NUM(i);
  432. assert (!(rn & 1));
  433. free_reg(i);
  434. free_reg(regnam[rn+1]);
  435. leave("free_double_reg");
  436. }
  437. void force_alloc_output() /* TMP HACK */
  438. {
  439. int i;
  440. enter("force_alloc_output");
  441. if (debug) { indent(); fprintf(stderr,"force_alloc_output\n"); }
  442. for (i = REG_NUM(reg_o0); i <= REG_NUM(reg_o5); i++)
  443. forced_alloc_reg(regnam[i]);
  444. leave("force_alloc_output");
  445. }
  446. void free_output()
  447. {
  448. int i;
  449. enter("free_output");
  450. leave("free_output");
  451. if (debug) { indent(); fprintf(stderr,"free_output\n"); }
  452. for (i = REG_NUM(reg_o0); i <= REG_NUM(reg_o5); i++) {
  453. assert(reg[i].inuse > 0);
  454. reg[i].inuse--;
  455. }
  456. }
  457. void soft_alloc_reg(i)
  458. reg_t i;
  459. {
  460. enter("soft_alloc_reg");
  461. if (debug) { indent(); fprintf(stderr,"soft_alloc_reg(%s)\n", i); }
  462. /* assert(reg[REG_NUM(i)].inuse); */
  463. reg[REG_NUM(i)].inuse++;
  464. leave("soft_alloc_reg");
  465. }
  466. void forced_alloc_reg(i)
  467. reg_t i;
  468. {
  469. int r;
  470. enter("forced_alloc_reg");
  471. if (debug) { indent(); fprintf(stderr,"forced_alloc_reg(%s)\n", i); }
  472. r = REG_NUM(i);
  473. if (reg[r].inuse) {
  474. reg_t S1;
  475. char *V2;
  476. S1 = alloc_reg();
  477. if (debug) { indent(); fprintf(stderr,"---> inuse: moving to %s\n", S1); }
  478. "mov $i, $S1";
  479. subst_reg(i, S1);
  480. free_reg(S1);
  481. if (reg[r].inuse)
  482. panic("forced_alloc_reg: external owners left!");
  483. }
  484. reg[r].inuse = 1;
  485. leave("forced_alloc_reg");
  486. }
  487. void change_reg(r) /* to be called when register r changes */
  488. reg_t r;
  489. {
  490. int i;
  491. enter("change_reg");
  492. if (debug) { indent(); fprintf(stderr, "change_reg(%s)\n", r); }
  493. if (r != reg_g0)
  494. for (i = 0; i < c_count; i++)
  495. if (cache[i].reg == r || cache[i].reg2 == r) {
  496. reg_t S1;
  497. if (r >= reg_f0) {
  498. S1 = alloc_float();
  499. "fmovs $r, $S1";
  500. } else {
  501. S1 = alloc_reg();
  502. "mov $r, $S1";
  503. }
  504. subst_reg(r, S1);
  505. free_reg(S1);
  506. break;
  507. }
  508. leave("change_reg");
  509. }
  510. static void subst_reg(old, new)
  511. reg_t old, new;
  512. {
  513. int i;
  514. enter("subst_reg");
  515. if (debug) { indent(); fprintf(stderr,"subst_reg(%s, %s)\n", old, new); }
  516. for (i = 0; i < c_count; i++) {
  517. if (cache[i].reg == old) {
  518. cache[i].reg = new;
  519. free_reg(old);
  520. soft_alloc_reg(new);
  521. }
  522. if (cache[i].reg2 == old) {
  523. cache[i].reg2 = new;
  524. free_reg(old);
  525. soft_alloc_reg(new);
  526. }
  527. }
  528. leave("subst_reg");
  529. }
  530. int type_of_tos()
  531. {
  532. int r = 0;
  533. cache_need(1);
  534. if (tos->ext)
  535. r |= T_ext;
  536. if (tos->reg != reg_g0)
  537. if (tos->reg >= reg_f0)
  538. r |= T_float;
  539. else
  540. r |= T_reg;
  541. if (tos->reg2 != reg_g0)
  542. if (tos->reg2 >= reg_f0)
  543. r |= T_float2;
  544. else
  545. r |= T_reg2;
  546. if (tos->cst)
  547. r |= T_cst;
  548. return r;
  549. }
  550. arith top_const()
  551. {
  552. enter("top_const");
  553. assert(type_of_tos() == T_cst);
  554. if (debug) { indent(); fprintf(stderr,"top_const()=%d\n", tos->cst); }
  555. leave("top_const");
  556. return tos->cst;
  557. }
  558. reg_t pop_reg_reg(r)
  559. reg_t *r;
  560. {
  561. reg_t s;
  562. enter("pop_reg_reg");
  563. POP1;
  564. if (!(type_of_tos() & T_reg2))
  565. push_reg(pop_reg());
  566. assert(r);
  567. *r = tos->reg2;
  568. s = tos->reg;
  569. POP2;
  570. if (debug) { indent(); fprintf(stderr,"pop_reg_reg()=%s\n", s); fprint(codefile,"\t\t! "); dump_cache(codefile); }
  571. leave("pop_reg_reg");
  572. return s;
  573. }
  574. reg_t pop_reg_c13(n) /* returns reg_t + optional n (as string) */
  575. char *n;
  576. {
  577. reg_t S1, S2, S3;
  578. register char *V1;
  579. const_str_t V2;
  580. enter("pop_reg_c13");
  581. if (debug) { indent(); fprintf(stderr,"pop_reg_c13()=...\n"); }
  582. *n = '0';
  583. *(n+1) = 0;
  584. cache_need(1);
  585. if (tos->reg >= reg_f0) { /* convert float to int */
  586. S1= pop_float();
  587. S2= alloc_reg();
  588. "st $S1, [%fp+64]";
  589. "ld [%fp+64], $S2";
  590. free_reg(S1);
  591. S1 = S2;
  592. }
  593. else if (tos->reg2 != reg_g0) { /* add integers */
  594. S1 = pop_reg();
  595. }
  596. else if (tos->ext) {
  597. assert(tos->reg == reg_g0);
  598. S1 = alloc_reg();
  599. V1 = tos->ext;
  600. sprint(V2, "%d", tos->cst);
  601. "sethi %hi($V1+$V2), $S1";
  602. sprint(n, "%%lo(%s+%d)", tos->ext, tos->cst);
  603. free(V1);
  604. POP2;
  605. } else {
  606. S1 = tos->reg;
  607. if (!(const13(tos->cst))) {
  608. S3 = alloc_reg();
  609. sprint(V2, "%d", tos->cst);
  610. "sethi %hi($V2), $S3";
  611. if (tos->reg != reg_g0) {
  612. S2 = alloc_reg();
  613. "add $S3, $S1, $S2";
  614. free_reg(S1);
  615. free_reg(S3);
  616. S1 = S2;
  617. }
  618. else {
  619. free_reg(S1);
  620. S1 = S3;
  621. }
  622. tos->cst &= 0x3FF;
  623. }
  624. sprint(n, "%d", tos->cst);
  625. POP2;
  626. }
  627. if (debug) { indent(); fprint(codefile, "\t\t! %s+%s cache:", S1, n); dump_cache(codefile);}
  628. leave("pop_reg_c13");
  629. return S1;
  630. }
  631. reg_t pop_float()
  632. {
  633. reg_t S1, R1, R2;
  634. char *V1, *V2;
  635. enter("pop_float");
  636. cache_need(1);
  637. S1 = tos->reg;
  638. if (!(type_of_tos() & T_float)) {
  639. S1 = pop_reg();
  640. R2 = alloc_float();
  641. "st $S1, [%fp+64]";
  642. "ld [%fp+64], $R2";
  643. free_reg(S1);
  644. S1 = R2;
  645. }
  646. else if (tos->reg2 >= reg_f0) {
  647. R1 = tos->reg2;
  648. R2 = alloc_float();
  649. "fadds $S1, $R1, $R2";
  650. free_reg(S1);
  651. free_reg(R1);
  652. S1 = R2;
  653. POP2;
  654. } else
  655. POP2;
  656. if (debug) { indent(); fprint(codefile, "\t\t! %s cache:", S1); dump_cache(codefile); }
  657. leave("pop_float");
  658. return S1;
  659. }
  660. void inc_tos_reg(r)
  661. reg_t r;
  662. {
  663. enter("inc_tos_reg");
  664. if (debug) { indent(); fprintf(stderr, "inc_tos_reg(%s)\n", r); }
  665. if (type_of_tos() != T_reg)
  666. push_reg(pop_reg());
  667. tos->reg2 = r;
  668. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  669. leave("inc_tos_reg");
  670. }
  671. void inc_tos(n)
  672. arith n;
  673. {
  674. reg_t S1;
  675. char *V1, *V2;
  676. enter("inc_tos");
  677. if (debug) { indent(); fprintf(stderr,"inc_tos(%d)\n", n); }
  678. cache_need(1);
  679. if (tos->reg >= reg_f0)
  680. {
  681. S1= pop_reg();
  682. push_reg(S1);
  683. }
  684. else if (tos->reg2 != reg_g0) {
  685. S1= pop_reg();
  686. push_reg(S1);
  687. }
  688. tos->cst += n;
  689. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  690. leave("inc_tos");
  691. }
  692. #define INC_TOS if (c_count >= CACHE_SIZE) flush_part_cache(c_count/2,0,0,0); \
  693. tos = &cache[c_count++];
  694. void push_const(n)
  695. arith n;
  696. {
  697. enter("push_const");
  698. INC_TOS;
  699. tos->reg = reg_g0;
  700. tos->reg2 = reg_g0;
  701. tos->ext = 0;
  702. tos->cst = n;
  703. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  704. leave("push_const");
  705. }
  706. void push_reg(i)
  707. reg_t i;
  708. {
  709. enter("push_reg");
  710. assert(0 <= REG_NUM(i) && REG_NUM(i) < NR_REGS);
  711. INC_TOS;
  712. tos->reg = i;
  713. tos->reg2 = reg_g0;
  714. tos->ext = 0;
  715. tos->cst = 0;
  716. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  717. leave("push_reg");
  718. }
  719. void push_double_reg(i)
  720. reg_t i;
  721. {
  722. int rn;
  723. enter("push_double_reg");
  724. rn= REG_NUM(i);
  725. assert (!(rn & 1));
  726. INC_TOS;
  727. tos->ext = 0;
  728. tos->cst = 0;
  729. tos->reg = regnam[rn+1];
  730. tos->reg2 = reg_g0;
  731. INC_TOS;
  732. tos->ext = 0;
  733. tos->cst = 0;
  734. tos->reg = i;
  735. tos->reg2 = reg_g0;
  736. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  737. leave("push_double_reg");
  738. }
  739. void push_ext(s)
  740. char *s;
  741. {
  742. char *p;
  743. enter("push_ext");
  744. p = malloc(strlen(s)+1);
  745. assert(p);
  746. INC_TOS;
  747. tos->reg = reg_g0;
  748. tos->reg2 = reg_g0;
  749. tos->ext = strcpy(p, s);
  750. tos->cst = 0;
  751. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  752. leave("push_ext");
  753. }
  754. arith pop_const(n)
  755. char *n;
  756. {
  757. arith x;
  758. enter("pop_const");
  759. POP1;
  760. x = top_const();
  761. POP2;
  762. if (n)
  763. sprint(n, "%d", x);
  764. if (debug) { indent(); fprint(codefile, "\t\t! %d cache:", x); dump_cache(codefile); }
  765. leave("pop_const");
  766. return x;
  767. }
  768. void pop_reg_as(r)
  769. reg_t r;
  770. {
  771. reg_t S1, S2;
  772. register char *V1, *V3;
  773. const_str_t V2, c_str;
  774. char *tos_ext;
  775. reg_t tos_reg, tos_reg2;
  776. int tos_cst;
  777. enter("pop_reg_as");
  778. if (debug) { indent(); fprintf(stderr,"pop_reg_as(%s)=...\n", r); }
  779. if (c_count == 0) { /* special case */
  780. "ld [%l0], $r";
  781. "inc 4, %l0";
  782. } else if (r >= reg_f0) {
  783. if (tos->reg < reg_f0)
  784. {
  785. S1= pop_reg();
  786. change_reg(r);
  787. "st $S1, [%fp+64]";
  788. "ld [%fp+64], $r";
  789. free_reg(S1);
  790. }
  791. else
  792. {
  793. if (tos->reg2 == reg_g0) {
  794. S1= pop_float();
  795. change_reg(r);
  796. if (S1 != r)
  797. "fmovs $S1, $r";
  798. free_reg(S1);
  799. } else {
  800. V1 = tos->reg;
  801. V3 = tos->reg2;
  802. POP2;
  803. change_reg(r);
  804. "fadds $V1, $V3, $r";
  805. free_reg(V1);
  806. free_reg(V3);
  807. }
  808. }
  809. } else if (tos->reg >= reg_f0) {
  810. S1= pop_float();
  811. change_reg(r);
  812. "st $S1, [%fp+64]";
  813. "ld [%fp+64], $r";
  814. free_reg(S1);
  815. } else if (tos->ext) {
  816. assert(tos->reg == reg_g0);
  817. V1 = tos->ext;
  818. sprint(V2, "%d", tos->cst);
  819. "set $V1+$V2, $r";
  820. free(V1);
  821. POP2;
  822. } else {
  823. POP1;
  824. tos_reg= tos->reg;
  825. tos_reg2= tos->reg2;
  826. tos_cst= tos->cst;
  827. POP2;
  828. change_reg(r);
  829. if (!const13(tos_cst))
  830. {
  831. assert (tos_reg2 == reg_g0);
  832. if (tos_reg != reg_g0 || (tos_cst & 0x3ff))
  833. tos_reg2= alloc_reg();
  834. else
  835. {
  836. soft_alloc_reg(r);
  837. tos_reg2= r;
  838. }
  839. sprint(c_str, "%d", tos_cst);
  840. "sethi %hi($c_str), $tos_reg2";
  841. tos_cst &= 0x3ff;
  842. if (tos_reg == reg_g0)
  843. {
  844. tos_reg= tos_reg2;
  845. tos_reg2= reg_g0;
  846. }
  847. }
  848. if (tos_reg2 != reg_g0)
  849. {
  850. assert (tos_reg != reg_g0);
  851. if (tos_cst)
  852. S1= alloc_reg();
  853. else
  854. {
  855. soft_alloc_reg(r);
  856. S1= r;
  857. }
  858. "add $tos_reg, $tos_reg2, $S1";
  859. free_reg(tos_reg);
  860. free_reg(tos_reg2);
  861. tos_reg= S1;
  862. tos_reg2= reg_g0;
  863. }
  864. if (tos_cst)
  865. {
  866. sprint(c_str, "%d", tos_cst);
  867. soft_alloc_reg(r);
  868. "add $tos_reg, $c_str, $r";
  869. free_reg(tos_reg);
  870. tos_reg= r;
  871. }
  872. if (tos_reg != r)
  873. "mov $tos_reg, $r";
  874. free_reg(tos_reg);
  875. }
  876. leave("pop_reg_as");
  877. }
  878. void pop_double_reg_as(rdl)
  879. reg_t rdl;
  880. {
  881. reg_t rl, rh;
  882. reg_t rdh;
  883. reg_t t;
  884. int rn;
  885. enter("pop_double_reg_as");
  886. rn= REG_NUM(rdl);
  887. assert (!(rn & 1));
  888. rdh= regnam[rn+1];
  889. if (rdl>= reg_f0)
  890. {
  891. if (c_count == 0) {
  892. "ld [%l0], $rdl";
  893. "ld [%l0+4], $rdh";
  894. "inc 8, %l0";
  895. } else {
  896. if (type_of_tos() & T_float)
  897. rl= pop_float();
  898. else
  899. rl= pop_reg();
  900. if (type_of_tos() & T_float)
  901. rh= pop_float();
  902. else
  903. rh= pop_reg();
  904. change_reg(rdl);
  905. change_reg(rdh);
  906. if (rl < reg_f0 && rh < reg_f0)
  907. {
  908. "st $rl, [%fp+64]";
  909. "st $rh, [%fp+68]";
  910. "ldd [%fp+64], $rdl";
  911. free_reg(rl);
  912. free_reg(rh);
  913. }
  914. else if (rl < reg_f0)
  915. {
  916. if (rh != rdh)
  917. "fmovs $rh, $rdh";
  918. "st $rl, [%fp+64]";
  919. "ld [%fp+64], $rdl";
  920. free_reg(rl);
  921. free_reg(rh);
  922. }
  923. else if (rh < reg_f0)
  924. {
  925. if (rl != rdl)
  926. "fmovs $rl, $rdl";
  927. "st $rh, [%fp+64]";
  928. "ld [%fp+64], $rdh";
  929. free_reg(rl);
  930. free_reg(rh);
  931. } else {
  932. if (rdl == rl)
  933. free_reg(rl);
  934. if (rdh == rh)
  935. free_reg(rh);
  936. if (rdl == rh && rdh == rl)
  937. {
  938. t= alloc_float();
  939. "fmovs $rl, $t";
  940. free_reg(rl);
  941. rl= t;
  942. }
  943. if (rdl != rl && rdl != rh)
  944. {
  945. "fmovs $rl, $rdl";
  946. free_reg(rl);
  947. rl= rdl;
  948. }
  949. if (rdh != rh && rdh != rl)
  950. {
  951. "fmovs $rh, $rdh";
  952. free_reg(rh);
  953. rh= rdh;
  954. }
  955. if (rdl != rl && rdl != rh)
  956. {
  957. "fmovs $rl, $rdl";
  958. free_reg(rl);
  959. rl= rdl;
  960. }
  961. assert (rdl == rl && rdh == rh);
  962. }
  963. }
  964. }
  965. else
  966. {
  967. pop_reg_as (rdl);
  968. pop_reg_as (rdh);
  969. }
  970. leave("pop_double_reg_as");
  971. }
  972. reg_t pop_reg()
  973. {
  974. reg_t S1;
  975. enter("pop_reg");
  976. POP1;
  977. if (type_of_tos() == T_reg) {
  978. S1 = tos->reg;
  979. POP2;
  980. } else {
  981. S1 = alloc_reg();
  982. pop_reg_as(S1);
  983. }
  984. if (debug) { indent(); fprint(codefile, "\t\t! %s cache:", S1); dump_cache(codefile); }
  985. leave("pop_reg");
  986. return S1;
  987. }
  988. reg_t pop_double(sub_reg) /* pop_double_float actually */
  989. reg_t *sub_reg;
  990. {
  991. reg_t R1, R2, R3, R4;
  992. char *V1, *V2;
  993. enter("pop_double");
  994. if (c_count == 0) {
  995. R1 = alloc_double(&R2);
  996. "ld [%l0], $R1";
  997. "ld [%l0+4], $R2";
  998. "inc 8, %l0";
  999. if (sub_reg)
  1000. *sub_reg = R2;
  1001. } else {
  1002. cache_need(2);
  1003. if (tos->reg >= reg_f0 && tos[-1].reg >= reg_f0 &&
  1004. REG_NUM(tos->reg) == REG_NUM(tos[-1].reg)-1 &&
  1005. tos->reg2 == reg_g0 && tos[-1].reg2 == reg_g0)
  1006. {
  1007. R1= tos->reg;
  1008. if (sub_reg)
  1009. *sub_reg= tos[-1].reg;
  1010. POP2;
  1011. POP2;
  1012. } else {
  1013. R1= alloc_double(&R2);
  1014. if (sub_reg)
  1015. *sub_reg= R2;
  1016. if (tos->reg >= reg_f0 || tos[-1].reg >= reg_f0)
  1017. {
  1018. pop_reg_as(R1);
  1019. pop_reg_as(R2);
  1020. } else {
  1021. /* two normal registers */
  1022. R3= pop_reg();
  1023. R4= pop_reg();
  1024. "st $R3, [%fp+64]";
  1025. "st $R4, [%fp+68]";
  1026. "ldd [%fp+64], $R1";
  1027. free_reg(R3);
  1028. free_reg(R4);
  1029. }
  1030. }
  1031. }
  1032. leave("pop_double");
  1033. return R1;
  1034. }
  1035. void pop_nop(i)
  1036. int i;
  1037. {
  1038. const_str_t V1;
  1039. int j = i;
  1040. enter("pop_nop");
  1041. while (c_count && i) {
  1042. i--;
  1043. POP1;
  1044. free_reg(tos->reg);
  1045. free_reg(tos->reg2);
  1046. if (tos->ext)
  1047. free(tos->ext);
  1048. POP2;
  1049. }
  1050. if (i) {
  1051. sprint(V1, "%d", 4*i);
  1052. if (const13(4*i)) {
  1053. "inc $V1, %l0";
  1054. } else {
  1055. "set $V1, $reg_tmp";
  1056. "add %l0, $reg_tmp, %l0";
  1057. }
  1058. }
  1059. if (debug) { indent(); fprint(codefile, "\t\t! %dw cache:",j); dump_cache(codefile); }
  1060. leave("pop_nop");
  1061. }
  1062. check_cache()
  1063. {
  1064. int i;
  1065. if (debug)
  1066. for (i = 0; i < NR_REGS; i++)
  1067. fprintf(stderr, "%c", reg[i].inuse ? (reg[i].inuse)+48 : '.');
  1068. fprintf(stderr, "\n");
  1069. }
  1070. void flush_cache() /* flush the cache onto the stack */
  1071. {
  1072. enter("flush_cache");
  1073. if (debug) { indent(); fprintf(stderr,"flush_cache\n"); }
  1074. if (c_count)
  1075. flush_part_cache(c_count, 0, 0, 0);
  1076. /* TEST */
  1077. if (debug)
  1078. check_cache();
  1079. leave("flush_cache");
  1080. }
  1081. void cache_need(n)
  1082. int n;
  1083. {
  1084. enter("cache_need");
  1085. if (c_count < n)
  1086. (void) cache_read(n, 0);
  1087. assert(c_count >= n);
  1088. leave("cache_need");
  1089. }
  1090. static int cache_read(n, i)
  1091. int n;
  1092. int i;
  1093. {
  1094. const_str_t V1;
  1095. reg_t S1;
  1096. int j;
  1097. int old_c_count;
  1098. enter("cache_read");
  1099. if (debug) { indent(); fprintf(stderr,"cache_read(%d, %d)\n", n,i); }
  1100. if (i+c_count<n)
  1101. {
  1102. S1= alloc_reg();
  1103. old_c_count = cache_read(n, i+1);
  1104. sprint(V1, "%d", (old_c_count-1-i) * 4);
  1105. "ld [%l0+$V1], $S1";
  1106. cache[i].reg= S1;
  1107. cache[i].reg2= reg_g0;
  1108. cache[i].ext= 0;
  1109. cache[i].cst= 0;
  1110. if (!i)
  1111. {
  1112. sprint(V1, "%d", (old_c_count)*4);
  1113. "add $reg_sp, $V1, $reg_sp";
  1114. }
  1115. }
  1116. else
  1117. {
  1118. assert (i);
  1119. for (j= c_count-1; j>=0; j--)
  1120. cache[j+i]= cache[j];
  1121. c_count += i;
  1122. tos= &cache[c_count-1];
  1123. old_c_count = i;
  1124. }
  1125. leave("cache_read");
  1126. return old_c_count;
  1127. }
  1128. static void dump_cache(stream) /* to codefile! */
  1129. File *stream;
  1130. {
  1131. int i;
  1132. assert (c_count >= 0);
  1133. for (i = c_count -1; i >= 0; i--) {
  1134. if (cache[i].ext)
  1135. fprint(stream, "%s", cache[i].ext);
  1136. if (cache[i].reg != reg_g0) {
  1137. if (cache[i].ext)
  1138. fprint(stream, "+");
  1139. fprint(stream, "%s", cache[i].reg);
  1140. if (cache[i].reg2 != reg_g0) {
  1141. fprint(stream, "+");
  1142. fprint(stream, "%s", cache[i].reg2);
  1143. }
  1144. }
  1145. if (cache[i].cst || (!cache[i].ext && cache[i].reg == reg_g0)) {
  1146. if (cache[i].ext || cache[i].reg != reg_g0)
  1147. fprint(stream, "+");
  1148. fprint(stream, "%d", cache[i].cst);
  1149. }
  1150. fprint(stream, " ");
  1151. }
  1152. fprint(stream, "\n");
  1153. if (debug) check_cache();
  1154. }
  1155. void dup_tos(n)
  1156. int n;
  1157. {
  1158. reg_t a;
  1159. int i;
  1160. const_str_t i_str;
  1161. enter("dup_tos");
  1162. for (i = 0;i < n; i++) {
  1163. INC_TOS;
  1164. tos->reg = reg_g0;
  1165. tos->reg2 = reg_g0;
  1166. tos->cst = 0;
  1167. tos->ext = 0;
  1168. if (c_count > n) {
  1169. char *ext;
  1170. *tos = tos[-n];
  1171. if (tos->ext)
  1172. {
  1173. ext= malloc(strlen(tos->ext)+1);
  1174. strcpy(ext, tos->ext);
  1175. tos->ext= ext;
  1176. }
  1177. soft_alloc_reg(tos->reg);
  1178. soft_alloc_reg(tos->reg2);
  1179. } else {
  1180. a= alloc_reg();
  1181. sprint(i_str, "%d", (n-c_count)*4);
  1182. "ld [$reg_sp+$i_str], $a";
  1183. tos->reg = a;
  1184. }
  1185. }
  1186. if (debug) { indent(); fprint(codefile, "\t\t! "); dump_cache(codefile); }
  1187. leave("dup_tos");
  1188. }