asm.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. #include "l.h"
  2. #define LPUT(c)\
  3. {\
  4. cbp[0] = (c)>>24;\
  5. cbp[1] = (c)>>16;\
  6. cbp[2] = (c)>>8;\
  7. cbp[3] = (c);\
  8. cbp += 4;\
  9. cbc -= 4;\
  10. if(cbc <= 0)\
  11. cflush();\
  12. }
  13. #define CPUT(c)\
  14. {\
  15. cbp[0] = (c);\
  16. cbp++;\
  17. cbc--;\
  18. if(cbc <= 0)\
  19. cflush();\
  20. }
  21. long
  22. entryvalue(void)
  23. {
  24. char *a;
  25. Sym *s;
  26. a = INITENTRY;
  27. if(*a >= '0' && *a <= '9')
  28. return atolwhex(a);
  29. s = lookup(a, 0);
  30. if(s->type == 0)
  31. return INITTEXT;
  32. if(s->type != STEXT && s->type != SLEAF)
  33. diag("entry not text: %s", s->name);
  34. return s->value;
  35. }
  36. void
  37. asmb(void)
  38. {
  39. Prog *p;
  40. long t;
  41. Optab *o;
  42. if(debug['v'])
  43. Bprint(&bso, "%5.2f asm\n", cputime());
  44. Bflush(&bso);
  45. seek(cout, HEADR, 0);
  46. pc = INITTEXT;
  47. for(p = firstp; p != P; p = p->link) {
  48. if(p->as == ATEXT) {
  49. curtext = p;
  50. autosize = p->to.offset + 4;
  51. }
  52. if(p->pc != pc) {
  53. diag("phase error %lux sb %lux",
  54. p->pc, pc);
  55. if(!debug['a'])
  56. prasm(curp);
  57. pc = p->pc;
  58. }
  59. curp = p;
  60. o = oplook(p); /* could probably avoid this call */
  61. if(asmout(p, o, 0)) {
  62. p = p->link;
  63. pc += 4;
  64. }
  65. pc += o->size;
  66. }
  67. if(debug['a'])
  68. Bprint(&bso, "\n");
  69. Bflush(&bso);
  70. cflush();
  71. curtext = P;
  72. switch(HEADTYPE) {
  73. case 0:
  74. case 3:
  75. seek(cout, HEADR+textsize, 0);
  76. break;
  77. case 1:
  78. case 2:
  79. seek(cout, HEADR+textsize, 0);
  80. break;
  81. }
  82. for(t = 0; t < datsize; t += sizeof(buf)-100) {
  83. if(datsize-t > sizeof(buf)-100)
  84. datblk(t, sizeof(buf)-100);
  85. else
  86. datblk(t, datsize-t);
  87. }
  88. symsize = 0;
  89. lcsize = 0;
  90. if(!debug['s']) {
  91. if(debug['v'])
  92. Bprint(&bso, "%5.2f sym\n", cputime());
  93. Bflush(&bso);
  94. switch(HEADTYPE) {
  95. case 0:
  96. case 3:
  97. seek(cout, HEADR+textsize+datsize, 0);
  98. break;
  99. case 2:
  100. case 1:
  101. seek(cout, HEADR+textsize+datsize, 0);
  102. break;
  103. }
  104. if(!debug['s'])
  105. asmsym();
  106. if(debug['v'])
  107. Bprint(&bso, "%5.2f sp\n", cputime());
  108. Bflush(&bso);
  109. if(!debug['s'])
  110. asmlc();
  111. /* round up file length for boot image */
  112. if(HEADTYPE == 0 || HEADTYPE == 3)
  113. if((symsize+lcsize) & 1)
  114. CPUT(0);
  115. cflush();
  116. }
  117. seek(cout, 0L, 0);
  118. switch(HEADTYPE) {
  119. case 0:
  120. lput(0x1030107); /* magic and sections */
  121. lput(textsize); /* sizes */
  122. lput(datsize);
  123. lput(bsssize);
  124. lput(symsize); /* nsyms */
  125. lput(entryvalue()); /* va of entry */
  126. lput(0L);
  127. lput(lcsize);
  128. break;
  129. case 1:
  130. break;
  131. case 2:
  132. lput(4*13*13+7); /* magic */
  133. lput(textsize); /* sizes */
  134. lput(datsize);
  135. lput(bsssize);
  136. lput(symsize); /* nsyms */
  137. lput(entryvalue()); /* va of entry */
  138. lput(0L);
  139. lput(lcsize);
  140. break;
  141. case 3:
  142. lput(0x1030107); /* magic and sections */
  143. lput(0x90100000);
  144. #define SPARC_NOOP 0x01000000
  145. lput(SPARC_NOOP);
  146. lput(SPARC_NOOP);
  147. lput(SPARC_NOOP);
  148. lput(SPARC_NOOP);
  149. lput(SPARC_NOOP);
  150. lput(SPARC_NOOP);
  151. break;
  152. }
  153. cflush();
  154. }
  155. void
  156. lput(long l)
  157. {
  158. LPUT(l);
  159. }
  160. void
  161. cflush(void)
  162. {
  163. int n;
  164. n = sizeof(buf.cbuf) - cbc;
  165. if(n)
  166. write(cout, buf.cbuf, n);
  167. cbp = buf.cbuf;
  168. cbc = sizeof(buf.cbuf);
  169. }
  170. void
  171. asmsym(void)
  172. {
  173. Prog *p;
  174. Auto *a;
  175. Sym *s;
  176. int h;
  177. s = lookup("etext", 0);
  178. if(s->type == STEXT)
  179. putsymb(s->name, 'T', s->value, s->version);
  180. for(h=0; h<NHASH; h++)
  181. for(s=hash[h]; s!=S; s=s->link)
  182. switch(s->type) {
  183. case SCONST:
  184. putsymb(s->name, 'D', s->value, s->version);
  185. continue;
  186. case SDATA:
  187. putsymb(s->name, 'D', s->value+INITDAT, s->version);
  188. continue;
  189. case SBSS:
  190. putsymb(s->name, 'B', s->value+INITDAT, s->version);
  191. continue;
  192. case SFILE:
  193. putsymb(s->name, 'f', s->value, s->version);
  194. continue;
  195. }
  196. for(p=textp; p!=P; p=p->cond) {
  197. s = p->from.sym;
  198. if(s->type != STEXT && s->type != SLEAF)
  199. continue;
  200. /* filenames first */
  201. for(a=p->to.autom; a; a=a->link)
  202. if(a->type == D_FILE)
  203. putsymb(a->asym->name, 'z', a->aoffset, 0);
  204. else
  205. if(a->type == D_FILE1)
  206. putsymb(a->asym->name, 'Z', a->aoffset, 0);
  207. if(s->type == STEXT)
  208. putsymb(s->name, 'T', s->value, s->version);
  209. else
  210. putsymb(s->name, 'L', s->value, s->version);
  211. /* frame, auto and param after */
  212. putsymb(".frame", 'm', p->to.offset+4, 0);
  213. for(a=p->to.autom; a; a=a->link)
  214. if(a->type == D_AUTO)
  215. putsymb(a->asym->name, 'a', -a->aoffset, 0);
  216. else
  217. if(a->type == D_PARAM)
  218. putsymb(a->asym->name, 'p', a->aoffset, 0);
  219. }
  220. if(debug['v'] || debug['n'])
  221. Bprint(&bso, "symsize = %lud\n", symsize);
  222. Bflush(&bso);
  223. }
  224. void
  225. putsymb(char *s, int t, long v, int ver)
  226. {
  227. int i, f;
  228. if(t == 'f')
  229. s++;
  230. LPUT(v);
  231. if(ver)
  232. t += 'a' - 'A';
  233. CPUT(t+0x80); /* 0x80 is variable length */
  234. if(t == 'Z' || t == 'z') {
  235. CPUT(s[0]);
  236. for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
  237. CPUT(s[i]);
  238. CPUT(s[i+1]);
  239. }
  240. CPUT(0);
  241. CPUT(0);
  242. i++;
  243. }
  244. else {
  245. for(i=0; s[i]; i++)
  246. CPUT(s[i]);
  247. CPUT(0);
  248. }
  249. symsize += 4 + 1 + i + 1;
  250. if(debug['n']) {
  251. if(t == 'z' || t == 'Z') {
  252. Bprint(&bso, "%c %.8lux ", t, v);
  253. for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
  254. f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
  255. Bprint(&bso, "/%x", f);
  256. }
  257. Bprint(&bso, "\n");
  258. return;
  259. }
  260. if(ver)
  261. Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
  262. else
  263. Bprint(&bso, "%c %.8lux %s\n", t, v, s);
  264. }
  265. }
  266. #define MINLC 4
  267. void
  268. asmlc(void)
  269. {
  270. long oldpc, oldlc;
  271. Prog *p;
  272. long v, s;
  273. oldpc = INITTEXT;
  274. oldlc = 0;
  275. for(p = firstp; p != P; p = p->link) {
  276. if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
  277. if(p->as == ATEXT)
  278. curtext = p;
  279. if(debug['L'])
  280. Bprint(&bso, "%6lux %P\n",
  281. p->pc, p);
  282. continue;
  283. }
  284. if(debug['L'])
  285. Bprint(&bso, "\t\t%6ld", lcsize);
  286. v = (p->pc - oldpc) / MINLC;
  287. while(v) {
  288. s = 127;
  289. if(v < 127)
  290. s = v;
  291. CPUT(s+128); /* 129-255 +pc */
  292. if(debug['L'])
  293. Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
  294. v -= s;
  295. lcsize++;
  296. }
  297. s = p->line - oldlc;
  298. oldlc = p->line;
  299. oldpc = p->pc + MINLC;
  300. if(s > 64 || s < -64) {
  301. CPUT(0); /* 0 vv +lc */
  302. CPUT(s>>24);
  303. CPUT(s>>16);
  304. CPUT(s>>8);
  305. CPUT(s);
  306. if(debug['L']) {
  307. if(s > 0)
  308. Bprint(&bso, " lc+%ld(%d,%ld)\n",
  309. s, 0, s);
  310. else
  311. Bprint(&bso, " lc%ld(%d,%ld)\n",
  312. s, 0, s);
  313. Bprint(&bso, "%6lux %P\n",
  314. p->pc, p);
  315. }
  316. lcsize += 5;
  317. continue;
  318. }
  319. if(s > 0) {
  320. CPUT(0+s); /* 1-64 +lc */
  321. if(debug['L']) {
  322. Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
  323. Bprint(&bso, "%6lux %P\n",
  324. p->pc, p);
  325. }
  326. } else {
  327. CPUT(64-s); /* 65-128 -lc */
  328. if(debug['L']) {
  329. Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
  330. Bprint(&bso, "%6lux %P\n",
  331. p->pc, p);
  332. }
  333. }
  334. lcsize++;
  335. }
  336. while(lcsize & 1) {
  337. s = 129;
  338. CPUT(s);
  339. lcsize++;
  340. }
  341. if(debug['v'] || debug['L'])
  342. Bprint(&bso, "lcsize = %ld\n", lcsize);
  343. Bflush(&bso);
  344. }
  345. void
  346. datblk(long s, long n)
  347. {
  348. Prog *p;
  349. char *cast;
  350. long l, fl, j, d;
  351. int i, c;
  352. memset(buf.dbuf, 0, n+100);
  353. for(p = datap; p != P; p = p->link) {
  354. curp = p;
  355. l = p->from.sym->value + p->from.offset - s;
  356. c = p->reg;
  357. i = 0;
  358. if(l < 0) {
  359. if(l+c <= 0)
  360. continue;
  361. while(l < 0) {
  362. l++;
  363. i++;
  364. }
  365. }
  366. if(l >= n)
  367. continue;
  368. if(p->as != AINIT && p->as != ADYNT) {
  369. for(j=l+(c-i)-1; j>=l; j--)
  370. if(buf.dbuf[j]) {
  371. print("%P\n", p);
  372. diag("multiple initialization");
  373. break;
  374. }
  375. }
  376. switch(p->to.type) {
  377. default:
  378. diag("unknown mode in initialization\n%P", p);
  379. break;
  380. case D_FCONST:
  381. switch(c) {
  382. default:
  383. case 4:
  384. fl = ieeedtof(&p->to.ieee);
  385. cast = (char*)&fl;
  386. for(; i<c; i++) {
  387. buf.dbuf[l] = cast[fnuxi8[i+4]];
  388. l++;
  389. }
  390. break;
  391. case 8:
  392. cast = (char*)&p->to.ieee;
  393. for(; i<c; i++) {
  394. buf.dbuf[l] = cast[fnuxi8[i]];
  395. l++;
  396. }
  397. break;
  398. }
  399. break;
  400. case D_SCONST:
  401. for(; i<c; i++) {
  402. buf.dbuf[l] = p->to.sval[i];
  403. l++;
  404. }
  405. break;
  406. case D_CONST:
  407. d = p->to.offset;
  408. if(p->to.sym) {
  409. if(p->to.sym->type == STEXT ||
  410. p->to.sym->type == SLEAF)
  411. d += p->to.sym->value;
  412. if(p->to.sym->type == SDATA)
  413. d += p->to.sym->value + INITDAT;
  414. if(p->to.sym->type == SBSS)
  415. d += p->to.sym->value + INITDAT;
  416. }
  417. cast = (char*)&d;
  418. switch(c) {
  419. default:
  420. diag("bad nuxi %d %d\n%P", c, i, curp);
  421. break;
  422. case 1:
  423. for(; i<c; i++) {
  424. buf.dbuf[l] = cast[inuxi1[i]];
  425. l++;
  426. }
  427. break;
  428. case 2:
  429. for(; i<c; i++) {
  430. buf.dbuf[l] = cast[inuxi2[i]];
  431. l++;
  432. }
  433. break;
  434. case 4:
  435. for(; i<c; i++) {
  436. buf.dbuf[l] = cast[inuxi4[i]];
  437. l++;
  438. }
  439. break;
  440. }
  441. break;
  442. }
  443. }
  444. write(cout, buf.dbuf, n);
  445. }
  446. #define OP2(x) (0x80000000|((x)<<19))
  447. #define OP3(x) (0xc0000000|((x)<<19))
  448. #define OPB(x) (0x00800000|((x)<<25))
  449. #define OPT(x) (0x81d02000|((x)<<25))
  450. #define OPF1(x) (0x81a00000|((x)<<5))
  451. #define OPF2(x) (0x81a80000|((x)<<5))
  452. #define OPFB(x) (0x01800000|((x)<<25))
  453. #define OP_RRR(op,r1,r2,r3)\
  454. (0x00000000 | op |\
  455. (((r1)&31L)<<0) |\
  456. (((r2)&31L)<<14) |\
  457. (((r3)&31L)<<25))
  458. #define OP_IRR(op,i,r2,r3)\
  459. (0x00002000L | (op) |\
  460. (((i)&0x1fffL)<<0) |\
  461. (((r2)&31L)<<14) |\
  462. (((r3)&31L)<<25))
  463. #define OP_BRA(op,pc)\
  464. ((op) |\
  465. (((pc)&0x3fffff)<<0))
  466. int
  467. asmout(Prog *p, Optab *o, int aflag)
  468. {
  469. long o1, o2, o3, o4, o5, v;
  470. Prog *ct;
  471. int r;
  472. o1 = 0;
  473. o2 = 0;
  474. o3 = 0;
  475. o4 = 0;
  476. o5 = 0;
  477. switch(o->type) {
  478. default:
  479. if(aflag)
  480. return 0;
  481. diag("unknown type %d", o->type);
  482. if(!debug['a'])
  483. prasm(p);
  484. break;
  485. case 0: /* pseudo ops */
  486. if(aflag) {
  487. if(p->link) {
  488. if(p->as == ATEXT) {
  489. ct = curtext;
  490. o2 = autosize;
  491. curtext = p;
  492. autosize = p->to.offset + 4;
  493. o1 = asmout(p->link, oplook(p->link), aflag);
  494. curtext = ct;
  495. autosize = o2;
  496. } else
  497. o1 = asmout(p->link, oplook(p->link), aflag);
  498. }
  499. return o1;
  500. }
  501. break;
  502. case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
  503. o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg);
  504. break;
  505. case 2: /* mov $c,r ==> add r1,r0,r2 */
  506. r = p->from.reg;
  507. if(r == NREG)
  508. r = o->param;
  509. v = regoff(&p->from);
  510. o1 = OP_IRR(opcode(AADD), v, r, p->to.reg);
  511. break;
  512. case 3: /* mov soreg, r */
  513. r = p->from.reg;
  514. if(r == NREG)
  515. r = o->param;
  516. v = regoff(&p->from);
  517. if(v == 0 && p->reg != NREG)
  518. o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg);
  519. else
  520. o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
  521. break;
  522. case 4: /* mov r, soreg */
  523. r = p->to.reg;
  524. if(r == NREG)
  525. r = o->param;
  526. v = regoff(&p->to);
  527. if(v == 0 && p->reg != NREG)
  528. o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg);
  529. else
  530. o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg);
  531. break;
  532. case 5: /* mov $lcon, reg => sethi, add */
  533. v = regoff(&p->from);
  534. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  535. o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
  536. break;
  537. case 6: /* mov asi, r[+r] */
  538. o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg);
  539. o1 |= (1<<23) | ((p->from.offset&0xff)<<5);
  540. break;
  541. case 7: /* mov [+r]r, asi */
  542. o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg);
  543. o1 |= (1<<23) | ((p->to.offset&0xff)<<5);
  544. break;
  545. case 8: /* mov r, preg and mov preg, r */
  546. if(p->to.type == D_PREG) {
  547. r = p->from.reg;
  548. switch(p->to.reg)
  549. {
  550. default:
  551. diag("unknown register P%d", p->to.reg);
  552. case D_Y:
  553. o1 = OP2(48); /* wry */
  554. break;
  555. case D_PSR:
  556. o1 = OP2(49); /* wrpsr */
  557. break;
  558. case D_WIM:
  559. o1 = OP2(50); /* wrwim */
  560. break;
  561. case D_TBR:
  562. o1 = OP2(51); /* wrtbr */
  563. break;
  564. }
  565. o1 = OP_IRR(o1, 0, r, 0);
  566. break;
  567. }
  568. if(p->from.type == D_PREG) {
  569. r = p->to.reg;
  570. switch(p->from.reg)
  571. {
  572. default:
  573. diag("unknown register P%d", p->to.reg);
  574. case D_Y:
  575. o1 = OP2(40); /* rdy */
  576. break;
  577. case D_PSR:
  578. o1 = OP2(41); /* rdpsr */
  579. break;
  580. case D_WIM:
  581. o1 = OP2(42); /* rdwim */
  582. break;
  583. case D_TBR:
  584. o1 = OP2(43); /* rdtbr */
  585. break;
  586. }
  587. o1 = OP_RRR(o1, 0, 0, r);
  588. break;
  589. }
  590. break;
  591. case 9: /* movb r,r */
  592. v = 24;
  593. if(p->as == AMOVH || p->as == AMOVHU)
  594. v = 16;
  595. r = ASRA;
  596. if(p->as == AMOVBU || p->as == AMOVHU)
  597. r = ASRL;
  598. o1 = OP_IRR(opcode(ASLL), v, p->from.reg, p->to.reg);
  599. o2 = OP_IRR(opcode(r), v, p->to.reg, p->to.reg);
  600. break;
  601. case 10: /* mov $loreg, reg */
  602. r = p->from.reg;
  603. if(r == NREG)
  604. r = o->param;
  605. v = regoff(&p->from);
  606. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  607. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  608. o3 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
  609. break;
  610. case 11: /* mov loreg, r */
  611. r = p->from.reg;
  612. if(r == NREG)
  613. r = o->param;
  614. v = regoff(&p->from);
  615. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  616. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  617. o3 = OP_IRR(opcode(p->as), (v&0x3ff), REGTMP, p->to.reg);
  618. break;
  619. case 12: /* mov r, loreg */
  620. r = p->to.reg;
  621. if(r == NREG)
  622. r = o->param;
  623. v = regoff(&p->to);
  624. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  625. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  626. o3 = OP_IRR(opcode(p->as+AEND), (v&0x3ff), REGTMP, p->from.reg);
  627. break;
  628. case 13: /* mov $ucon, r */
  629. v = regoff(&p->from);
  630. o1 = 0x1000000 | (p->to.reg<<25) | ((v>>10) & 0x3fffff); /* sethi */
  631. break;
  632. case 20: /* op $scon,r */
  633. v = regoff(&p->from);
  634. r = p->reg;
  635. if(r == NREG)
  636. r = p->to.reg;
  637. o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
  638. break;
  639. case 21: /* op r1,r2 */
  640. r = p->reg;
  641. if(r == NREG)
  642. r = p->to.reg;
  643. o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
  644. break;
  645. case 22: /* op $lcon,r */
  646. v = regoff(&p->from);
  647. r = p->reg;
  648. if(r == NREG)
  649. r = p->to.reg;
  650. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  651. o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, REGTMP);
  652. o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
  653. break;
  654. case 23: /* cmp r,r */
  655. o1 = OP_RRR(opcode(ASUBCC), p->to.reg, p->from.reg, REGZERO);
  656. break;
  657. case 24: /* cmp r,$c */
  658. v = regoff(&p->to);
  659. o1 = OP_IRR(opcode(ASUBCC), v, p->from.reg, REGZERO);
  660. break;
  661. case 25: /* cmp $c,r BOTCH, fix compiler */
  662. v = regoff(&p->from);
  663. o1 = OP_IRR(opcode(AADD), v, NREG, REGTMP);
  664. o2 = OP_RRR(opcode(ASUBCC), p->to.reg, REGTMP, REGZERO);
  665. break;
  666. case 26: /* op $ucon,r */
  667. v = regoff(&p->from);
  668. r = p->reg;
  669. if(r == NREG)
  670. r = p->to.reg;
  671. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  672. o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
  673. break;
  674. case 30: /* jmp/jmpl soreg */
  675. if(aflag)
  676. return 0;
  677. v = regoff(&p->to);
  678. r = p->reg;
  679. if(r == NREG && p->as == AJMPL)
  680. r = 15;
  681. o1 = OP_IRR(opcode(AJMPL), v, p->to.reg, r);
  682. break;
  683. case 31: /* ba jmp */
  684. if(aflag)
  685. return 0;
  686. r = p->as;
  687. if(r == AJMP)
  688. r = ABA;
  689. v = 0;
  690. if(p->cond)
  691. v = p->cond->pc - p->pc;
  692. o1 = OP_BRA(opcode(r), v/4);
  693. if(r == ABA && p->link && p->cond && isnop(p->link)) {
  694. o2 = asmout(p->cond, oplook(p->cond), 1);
  695. if(o2) {
  696. o1 += 1;
  697. if(debug['a'])
  698. Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
  699. LPUT(o1);
  700. LPUT(o2);
  701. return 1;
  702. }
  703. /* cant set annul here because pc has already been counted */
  704. }
  705. break;
  706. case 32: /* jmpl lbra */
  707. if(aflag)
  708. return 0;
  709. v = 0;
  710. if(p->cond)
  711. v = p->cond->pc - p->pc;
  712. r = p->reg;
  713. if(r != NREG && r != 15)
  714. diag("cant jmpl other than R15");
  715. o1 = 0x40000000 | ((v/4) & 0x3fffffffL); /* call */
  716. if(p->link && p->cond && isnop(p->link)) {
  717. o2 = asmout(p->cond, oplook(p->cond), 1);
  718. if(o2) {
  719. o1 += 1;
  720. if(debug['a'])
  721. Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
  722. LPUT(o1);
  723. LPUT(o2);
  724. return 1;
  725. }
  726. }
  727. break;
  728. case 33: /* trap r */
  729. if(aflag)
  730. return 0;
  731. o1 = opcode(p->as) | (p->from.reg<<14);
  732. break;
  733. case 34: /* rett r1,r2 -> jmpl (r1); rett (r2) */
  734. if(aflag)
  735. return 0;
  736. o1 = OP_IRR(opcode(AJMPL), 0, p->from.reg, REGZERO);
  737. o2 = OP_IRR(opcode(ARETT), 0, p->to.reg, REGZERO);
  738. break;
  739. case 40: /* ldfsr, stfsr, stdq */
  740. if(p->to.type == D_PREG) {
  741. r = p->from.reg;
  742. if(r == NREG)
  743. r = o->param;
  744. v = regoff(&p->from);
  745. if(p->to.reg == D_FSR) {
  746. o1 = OP_IRR(OP3(33), v, r, 0);
  747. break;
  748. }
  749. diag("unknown reg load %d", p->to.reg);
  750. } else {
  751. r = p->to.reg;
  752. if(r == NREG)
  753. r = o->param;
  754. v = regoff(&p->to);
  755. if(p->from.reg == D_FSR) {
  756. o1 = OP_IRR(OP3(37), v, r, 0);
  757. break;
  758. }
  759. if(p->as == AMOVD && p->from.reg == D_FPQ) {
  760. o1 = OP_IRR(OP3(38), v, r, 0);
  761. break;
  762. }
  763. diag("unknown reg store %d", p->from.reg);
  764. }
  765. break;
  766. case 41: /* ldf,ldd */
  767. r = p->from.reg;
  768. if(r == NREG)
  769. r = o->param;
  770. v = regoff(&p->from);
  771. if(p->as == AFMOVF || p->as == AMOVW) {
  772. o1 = OP_IRR(OP3(32), v, r, p->to.reg);
  773. break;
  774. }
  775. if(p->as == AMOVD || p->as == AFMOVD) {
  776. o1 = OP_IRR(OP3(35), v, r, p->to.reg);
  777. break;
  778. }
  779. diag("only MOVD and MOVW to FREG");
  780. break;
  781. case 42: /* ldd -> ldf,ldf */
  782. /* note should be ldd with proper allignment */
  783. r = p->from.reg;
  784. if(r == NREG)
  785. r = o->param;
  786. v = regoff(&p->from);
  787. o1 = OP_IRR(OP3(32), v, r, p->to.reg);
  788. o2 = OP_IRR(OP3(32), v+4, r, p->to.reg+1);
  789. break;
  790. case 43: /* stf */
  791. r = p->to.reg;
  792. if(r == NREG)
  793. r = o->param;
  794. v = regoff(&p->to);
  795. if(p->as == AFMOVF || p->as == AMOVW) {
  796. o1 = OP_IRR(OP3(36), v, r, p->from.reg);
  797. break;
  798. }
  799. if(p->as == AMOVD || p->as == AFMOVD) {
  800. o1 = OP_IRR(OP3(39), v, r, p->from.reg);
  801. break;
  802. }
  803. diag("only MOVD and MOVW from FREG");
  804. break;
  805. case 44: /* std -> stf,stf */
  806. /* note should be std with proper allignment */
  807. r = p->to.reg;
  808. if(r == NREG)
  809. r = o->param;
  810. v = regoff(&p->to);
  811. o1 = OP_IRR(OP3(36), v, r, p->from.reg);
  812. o2 = OP_IRR(OP3(36), v+4, r, p->from.reg+1);
  813. break;
  814. case 45: /* ldf lorg */
  815. r = p->from.reg;
  816. if(r == NREG)
  817. r = o->param;
  818. v = regoff(&p->from);
  819. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  820. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  821. o3 = OP_IRR(OP3(32), v&0x3ff, REGTMP, p->to.reg);
  822. break;
  823. case 46: /* ldd lorg -> ldf,ldf */
  824. /* note should be ldd with proper allignment */
  825. r = p->from.reg;
  826. if(r == NREG)
  827. r = o->param;
  828. v = regoff(&p->from);
  829. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  830. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  831. o3 = OP_IRR(OP3(32), (v&0x3ff), REGTMP, p->to.reg);
  832. o4 = OP_IRR(OP3(32), (v&0x3ff)+4, REGTMP, p->to.reg+1);
  833. break;
  834. case 47: /* stf lorg */
  835. r = p->to.reg;
  836. if(r == NREG)
  837. r = o->param;
  838. v = regoff(&p->to);
  839. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  840. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  841. o3 = OP_IRR(OP3(36), v&0x3ff, REGTMP, p->from.reg);
  842. break;
  843. case 48: /* std lorg -> stf,stf */
  844. /* note should be std with proper allignment */
  845. r = p->to.reg;
  846. if(r == NREG)
  847. r = o->param;
  848. v = regoff(&p->to);
  849. o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff); /* sethi */
  850. o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
  851. o3 = OP_IRR(OP3(36), (v&0x3ff), REGTMP, p->from.reg);
  852. o4 = OP_IRR(OP3(36), (v&0x3ff)+4, REGTMP, p->from.reg+1);
  853. break;
  854. case 49: /* fmovd -> fmovf,fmovf */
  855. o1 = OP_RRR(opcode(AFMOVF), p->from.reg, 0, p->to.reg);
  856. o2 = OP_RRR(opcode(AFMOVF), p->from.reg+1, 0, p->to.reg+1);
  857. break;
  858. case 50: /* fcmp */
  859. o1 = OP_RRR(opcode(p->as), p->to.reg, p->from.reg, 0);
  860. break;
  861. case 51: /* word */
  862. if(aflag)
  863. return 0;
  864. o1 = regoff(&p->from);
  865. break;
  866. case 52: /* div */
  867. r = p->reg;
  868. if(r == NREG)
  869. r = p->to.reg;
  870. o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
  871. o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
  872. o3 = OP_RRR(opcode(ADIV), p->from.reg, r, p->to.reg);
  873. break;
  874. case 53: /* divl */
  875. r = p->reg;
  876. if(r == NREG)
  877. r = p->to.reg;
  878. o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
  879. o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, p->to.reg);
  880. break;
  881. case 54: /* mod */
  882. r = p->reg;
  883. if(r == NREG)
  884. r = p->to.reg;
  885. o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
  886. o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
  887. o3 = OP_RRR(opcode(ADIV), p->from.reg, r, REGTMP);
  888. o4 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
  889. o5 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
  890. break;
  891. case 55: /* modl */
  892. r = p->reg;
  893. if(r == NREG)
  894. r = p->to.reg;
  895. o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
  896. o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, REGTMP);
  897. o3 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
  898. o4 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
  899. break;
  900. case 56: /* b(cc) -- annullable */
  901. if(aflag)
  902. return 0;
  903. r = p->as;
  904. v = 0;
  905. if(p->cond)
  906. v = p->cond->pc - p->pc;
  907. o1 = OP_BRA(opcode(r), v/4);
  908. if(p->link && p->cond && isnop(p->link))
  909. if(!debug['A']) {
  910. o2 = asmout(p->cond, oplook(p->cond), 2);
  911. if(o2) {
  912. o1 |= 1<<29; /* annul */
  913. o1 += 1;
  914. if(debug['a'])
  915. Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
  916. LPUT(o1);
  917. LPUT(o2);
  918. return 1;
  919. }
  920. }
  921. break;
  922. case 57: /* op r1,r2 with reserved rs1 */
  923. r = 0;
  924. o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
  925. break;
  926. }
  927. if(aflag)
  928. return o1;
  929. v = p->pc;
  930. switch(o->size) {
  931. default:
  932. if(debug['a'])
  933. Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
  934. break;
  935. case 4:
  936. if(debug['a'])
  937. Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
  938. LPUT(o1);
  939. break;
  940. case 8:
  941. if(debug['a'])
  942. Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
  943. LPUT(o1);
  944. LPUT(o2);
  945. break;
  946. case 12:
  947. if(debug['a'])
  948. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
  949. LPUT(o1);
  950. LPUT(o2);
  951. LPUT(o3);
  952. break;
  953. case 16:
  954. if(debug['a'])
  955. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
  956. v, o1, o2, o3, o4, p);
  957. LPUT(o1);
  958. LPUT(o2);
  959. LPUT(o3);
  960. LPUT(o4);
  961. break;
  962. case 20:
  963. if(debug['a'])
  964. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
  965. v, o1, o2, o3, o4, o5, p);
  966. LPUT(o1);
  967. LPUT(o2);
  968. LPUT(o3);
  969. LPUT(o4);
  970. LPUT(o5);
  971. break;
  972. }
  973. return 0;
  974. }
  975. int
  976. isnop(Prog *p)
  977. {
  978. if(p->as != AORN)
  979. return 0;
  980. if(p->reg != REGZERO && p->reg != NREG)
  981. return 0;
  982. if(p->from.type != D_REG || p->from.reg != REGZERO)
  983. return 0;
  984. if(p->to.type != D_REG || p->to.reg != REGZERO)
  985. return 0;
  986. return 1;
  987. }
  988. long
  989. opcode(int a)
  990. {
  991. switch(a) {
  992. case AADD: return OP2(0);
  993. case AADDCC: return OP2(16);
  994. case AADDX: return OP2(8);
  995. case AADDXCC: return OP2(24);
  996. case AMUL: return OP2(10);
  997. case ADIV: return OP2(15);
  998. case ADIVL: return OP2(14);
  999. case ATADDCC: return OP2(32);
  1000. case ATADDCCTV: return OP2(34);
  1001. case ASUB: return OP2(4);
  1002. case ASUBCC: return OP2(20);
  1003. case ASUBX: return OP2(12);
  1004. case ASUBXCC: return OP2(28);
  1005. case ATSUBCC: return OP2(33);
  1006. case ATSUBCCTV: return OP2(35);
  1007. case AMULSCC: return OP2(36);
  1008. case ASAVE: return OP2(60);
  1009. case ARESTORE: return OP2(61);
  1010. case AAND: return OP2(1);
  1011. case AANDCC: return OP2(17);
  1012. case AANDN: return OP2(5);
  1013. case AANDNCC: return OP2(21);
  1014. case AOR: return OP2(2);
  1015. case AORCC: return OP2(18);
  1016. case AORN: return OP2(6);
  1017. case AORNCC: return OP2(22);
  1018. case AXOR: return OP2(3);
  1019. case AXORCC: return OP2(19);
  1020. case AXNOR: return OP2(7);
  1021. case AXNORCC: return OP2(23);
  1022. case ASLL: return OP2(37);
  1023. case ASRL: return OP2(38);
  1024. case ASRA: return OP2(39);
  1025. case AJMPL:
  1026. case AJMP: return OP2(56);
  1027. case ARETT: return OP2(57);
  1028. case AMOVBU: return OP3(1); /* ldub */
  1029. case AMOVB: return OP3(9); /* ldsb */
  1030. case AMOVHU: return OP3(2); /* lduh */
  1031. case AMOVH: return OP3(10); /* ldsh */
  1032. case AMOVW: return OP3(0); /* ld */
  1033. case AMOVD: return OP3(3); /* ldd */
  1034. case AMOVBU+AEND:
  1035. case AMOVB+AEND:return OP3(5); /* stb */
  1036. case AMOVHU+AEND:
  1037. case AMOVH+AEND:return OP3(6); /* sth */
  1038. case AMOVW+AEND:return OP3(4); /* st */
  1039. case AMOVD+AEND:return OP3(7); /* std */
  1040. case ASWAP: /* swap is symmetric */
  1041. case ASWAP+AEND:return OP3(15);
  1042. case ATAS: return OP3(13); /* tas is really ldstub */
  1043. case ABN: return OPB(0);
  1044. case ABE: return OPB(1);
  1045. case ABLE: return OPB(2);
  1046. case ABL: return OPB(3);
  1047. case ABLEU: return OPB(4);
  1048. case ABCS: return OPB(5);
  1049. case ABNEG: return OPB(6);
  1050. case ABVS: return OPB(7);
  1051. case ABA: return OPB(8);
  1052. case ABNE: return OPB(9);
  1053. case ABG: return OPB(10);
  1054. case ABGE: return OPB(11);
  1055. case ABGU: return OPB(12);
  1056. case ABCC: return OPB(13);
  1057. case ABPOS: return OPB(14);
  1058. case ABVC: return OPB(15);
  1059. case AFBA: return OPFB(8);
  1060. case AFBE: return OPFB(9);
  1061. case AFBG: return OPFB(6);
  1062. case AFBGE: return OPFB(11);
  1063. case AFBL: return OPFB(4);
  1064. case AFBLE: return OPFB(13);
  1065. case AFBLG: return OPFB(2);
  1066. case AFBN: return OPFB(0);
  1067. case AFBNE: return OPFB(1);
  1068. case AFBO: return OPFB(15);
  1069. case AFBU: return OPFB(7);
  1070. case AFBUE: return OPFB(10);
  1071. case AFBUG: return OPFB(5);
  1072. case AFBUGE: return OPFB(12);
  1073. case AFBUL: return OPFB(3);
  1074. case AFBULE: return OPFB(14);
  1075. case ATN: return OPT(0);
  1076. case ATE: return OPT(1);
  1077. case ATLE: return OPT(2);
  1078. case ATL: return OPT(3);
  1079. case ATLEU: return OPT(4);
  1080. case ATCS: return OPT(5);
  1081. case ATNEG: return OPT(6);
  1082. case ATVS: return OPT(7);
  1083. case ATA: return OPT(8);
  1084. case ATNE: return OPT(9);
  1085. case ATG: return OPT(10);
  1086. case ATGE: return OPT(11);
  1087. case ATGU: return OPT(12);
  1088. case ATCC: return OPT(13);
  1089. case ATPOS: return OPT(14);
  1090. case ATVC: return OPT(15);
  1091. case AFADDF: return OPF1(65);
  1092. case AFADDD: return OPF1(66);
  1093. case AFADDX: return OPF1(67);
  1094. case AFSUBF: return OPF1(69);
  1095. case AFSUBD: return OPF1(70);
  1096. case AFSUBX: return OPF1(71);
  1097. case AFMULF: return OPF1(73);
  1098. case AFMULD: return OPF1(74);
  1099. case AFMULX: return OPF1(75);
  1100. case AFDIVF: return OPF1(77);
  1101. case AFDIVD: return OPF1(78);
  1102. case AFDIVX: return OPF1(79);
  1103. case AFMOVF: return OPF1(1);
  1104. case AFNEGF: return OPF1(5);
  1105. case AFABSF: return OPF1(9);
  1106. case AFSQRTF: return OPF1(41);
  1107. case AFSQRTD: return OPF1(42);
  1108. case AFSQRTX: return OPF1(43);
  1109. case AFMOVWF: return OPF1(196);
  1110. case AFMOVWD: return OPF1(200);
  1111. case AFMOVWX: return OPF1(204);
  1112. case AFMOVFW: return OPF1(209);
  1113. case AFMOVDW: return OPF1(210);
  1114. case AFMOVXW: return OPF1(211);
  1115. case AFMOVFD: return OPF1(201);
  1116. case AFMOVFX: return OPF1(205);
  1117. case AFMOVDF: return OPF1(198);
  1118. case AFMOVDX: return OPF1(206);
  1119. case AFMOVXF: return OPF1(199);
  1120. case AFMOVXD: return OPF1(203);
  1121. case AFCMPF: return OPF2(81);
  1122. case AFCMPD: return OPF2(82);
  1123. case AFCMPX: return OPF2(83);
  1124. case AFCMPEF: return OPF2(85);
  1125. case AFCMPED: return OPF2(86);
  1126. case AFCMPEX: return OPF2(87);
  1127. case AUNIMP: return 0;
  1128. }
  1129. diag("bad opcode %A", a);
  1130. return 0;
  1131. }