asm.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220
  1. #include "l.h"
  2. #define LPUT(c)\
  3. {\
  4. cbp[0] = (c);\
  5. cbp[1] = (c)>>8;\
  6. cbp[2] = (c)>>16;\
  7. cbp[3] = (c)>>24;\
  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. #define VLPUT(c)\
  22. {\
  23. cbp[0] = (c);\
  24. cbp[1] = (c)>>8;\
  25. cbp[2] = (c)>>16;\
  26. cbp[3] = (c)>>24;\
  27. cbp[4] = (c)>>32;\
  28. cbp[5] = (c)>>40;\
  29. cbp[6] = (c)>>48;\
  30. cbp[7] = (c)>>56;\
  31. cbp += 8;\
  32. cbc -= 8;\
  33. if(cbc <= 0)\
  34. cflush();\
  35. }
  36. #define LPUTBE(c)\
  37. {\
  38. cbp[0] = (c)>>24;\
  39. cbp[1] = (c)>>16;\
  40. cbp[2] = (c)>>8;\
  41. cbp[3] = (c);\
  42. cbp += 4;\
  43. cbc -= 4;\
  44. if(cbc <= 0)\
  45. cflush();\
  46. }
  47. long
  48. entryvalue(void)
  49. {
  50. char *a;
  51. Sym *s;
  52. a = INITENTRY;
  53. if(*a >= '0' && *a <= '9')
  54. return atolwhex(a);
  55. s = lookup(a, 0);
  56. if(s->type == 0)
  57. return INITTEXT;
  58. if(s->type != STEXT && s->type != SLEAF)
  59. diag("entry not text: %s", s->name);
  60. return s->value;
  61. }
  62. void
  63. asmb(void)
  64. {
  65. Prog *p;
  66. vlong t;
  67. Optab *o;
  68. if(debug['v'])
  69. Bprint(&bso, "%5.2f asm\n", cputime());
  70. Bflush(&bso);
  71. seek(cout, HEADR, 0);
  72. pc = INITTEXT;
  73. for(p = firstp; p != P; p = p->link) {
  74. if(p->as == ATEXT) {
  75. curtext = p;
  76. autosize = p->to.offset + 8;
  77. }
  78. if(p->pc != pc) {
  79. diag("phase error %lux sb %lux",
  80. p->pc, pc);
  81. if(!debug['a'])
  82. prasm(curp);
  83. pc = p->pc;
  84. }
  85. if (p->as == AMOVQ || p->as == AMOVT) {
  86. if ((p->from.reg == REGSP) && (p->from.offset&7) != 0
  87. || (p->to.reg == REGSP) && (p->to.offset&7) != 0)
  88. diag("bad stack alignment: %P", p);
  89. if ((p->from.reg == REGSB) && (p->from.offset&7) != 0
  90. || (p->to.reg == REGSB) && (p->to.offset&7) != 0)
  91. diag("bad global alignment: %P", p);
  92. }
  93. curp = p;
  94. o = oplook(p); /* could probably avoid this call */
  95. if(asmout(p, o)) {
  96. p = p->link;
  97. pc += 4;
  98. }
  99. pc += o->size;
  100. }
  101. if(debug['a'])
  102. Bprint(&bso, "\n");
  103. Bflush(&bso);
  104. cflush();
  105. curtext = P;
  106. switch(HEADTYPE) {
  107. case 0:
  108. seek(cout, rnd(HEADR+textsize, 8192), 0);
  109. break;
  110. case 1:
  111. case 2:
  112. case 3:
  113. seek(cout, HEADR+textsize, 0);
  114. break;
  115. }
  116. for(t = 0; t < datsize; t += sizeof(buf)-100) {
  117. if(datsize-t > sizeof(buf)-100)
  118. datblk(t, sizeof(buf)-100);
  119. else
  120. datblk(t, datsize-t);
  121. }
  122. symsize = 0;
  123. lcsize = 0;
  124. if(!debug['s']) {
  125. if(debug['v'])
  126. Bprint(&bso, "%5.2f sym\n", cputime());
  127. Bflush(&bso);
  128. switch(HEADTYPE) {
  129. case 0:
  130. seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
  131. break;
  132. case 2:
  133. case 1:
  134. case 3:
  135. seek(cout, HEADR+textsize+datsize, 0);
  136. break;
  137. }
  138. if(!debug['s'])
  139. asmsym();
  140. if(debug['v'])
  141. Bprint(&bso, "%5.2f pc\n", cputime());
  142. Bflush(&bso);
  143. if(!debug['s'])
  144. asmlc();
  145. cflush();
  146. }
  147. if(debug['v'])
  148. Bprint(&bso, "%5.2f header\n", cputime());
  149. Bflush(&bso);
  150. seek(cout, 0L, 0);
  151. switch(HEADTYPE) {
  152. case 0:
  153. lput(0x0183L); /* magic and sections */
  154. lput(0L); /* time and date */
  155. vlput(rnd(HEADR+textsize, 8192)+datsize);
  156. lput(symsize); /* nsyms */
  157. lput(0x50L|(7L<<16)); /* size of optional hdr and flags */
  158. lput(0413|(0x101L<<16)); /* magic and version */
  159. lput(-1); /* pad for alignment */
  160. vlput(rnd(HEADR+textsize, 8192)); /* sizes */
  161. vlput(datsize);
  162. vlput(bsssize);
  163. vlput(entryvalue()); /* va of entry */
  164. vlput(INITTEXT-HEADR); /* va of base of text */
  165. vlput(INITDAT); /* va of base of data */
  166. vlput(INITDAT+datsize); /* va of base of bss */
  167. lput(~0L); /* gp reg mask */
  168. /* dubious stuff starts here */
  169. lput(0L);
  170. lput(0L);
  171. lput(0L);
  172. lput(0L);
  173. lput(~0L); /* gp value ?? */
  174. break;
  175. case 1:
  176. lput(0x0183L); /* magic and sections */
  177. lput(0L); /* time and date */
  178. vlput(HEADR+textsize+datsize);
  179. lput(symsize); /* nsyms */
  180. lput(0x54L|(7L<<16)); /* size of optional hdr and flags */
  181. lput(0407|(0x101L<<16)); /* magic and version */
  182. lput(-1); /* pad for alignment */
  183. vlput(textsize); /* sizes */
  184. vlput(datsize);
  185. vlput(bsssize);
  186. vlput(entryvalue()); /* va of entry */
  187. vlput(INITTEXT); /* va of base of text */
  188. vlput(INITDAT); /* va of base of data */
  189. vlput(INITDAT+datsize); /* va of base of bss */
  190. lput(~0L); /* gp reg mask */
  191. /* dubious stuff starts here */
  192. lput(lcsize);
  193. lput(0L);
  194. lput(0L);
  195. lput(0L);
  196. lput(~0L); /* gp value ?? */
  197. lput(0L); /* complete mystery */
  198. break;
  199. case 2:
  200. lputbe(0x84b); /* magic */
  201. lputbe(textsize); /* sizes */
  202. lputbe(datsize);
  203. lputbe(bsssize);
  204. lputbe(symsize); /* nsyms */
  205. lputbe(entryvalue()); /* va of entry */
  206. lputbe(0L);
  207. lputbe(lcsize);
  208. break;
  209. case 3:
  210. /* ``headerless'' boot image -- magic no is a branch */
  211. lput(0xc3e00007); /* magic (branch) */
  212. lputbe(textsize); /* sizes */
  213. lputbe(datsize);
  214. lputbe(bsssize);
  215. lputbe(symsize); /* nsyms */
  216. lputbe(entryvalue()); /* va of entry */
  217. lputbe(0L);
  218. lputbe(lcsize);
  219. break;
  220. }
  221. cflush();
  222. }
  223. void
  224. lput(long l)
  225. {
  226. LPUT(l);
  227. }
  228. void
  229. lputbe(long l)
  230. {
  231. LPUTBE(l);
  232. }
  233. void
  234. vlput(vlong l)
  235. {
  236. VLPUT(l);
  237. }
  238. void
  239. cflush(void)
  240. {
  241. int n;
  242. n = sizeof(buf.cbuf) - cbc;
  243. if(n)
  244. write(cout, buf.cbuf, n);
  245. cbp = buf.cbuf;
  246. cbc = sizeof(buf.cbuf);
  247. }
  248. void
  249. asmsym(void)
  250. {
  251. Prog *p;
  252. Auto *a;
  253. Sym *s;
  254. int h;
  255. s = lookup("etext", 0);
  256. if(s->type == STEXT)
  257. putsymb(s->name, 'T', s->value, s->version);
  258. for(h=0; h<NHASH; h++)
  259. for(s=hash[h]; s!=S; s=s->link)
  260. switch(s->type) {
  261. case SCONST:
  262. putsymb(s->name, 'D', s->value, s->version);
  263. continue;
  264. case SDATA:
  265. putsymb(s->name, 'D', s->value+INITDAT, s->version);
  266. continue;
  267. case SBSS:
  268. putsymb(s->name, 'B', s->value+INITDAT, s->version);
  269. continue;
  270. case SFILE:
  271. putsymb(s->name, 'f', s->value, s->version);
  272. continue;
  273. }
  274. for(p=textp; p!=P; p=p->cond) {
  275. s = p->from.sym;
  276. if(s->type != STEXT && s->type != SLEAF)
  277. continue;
  278. /* filenames first */
  279. for(a=p->to.autom; a; a=a->link)
  280. if(a->type == D_FILE)
  281. putsymb(a->sym->name, 'z', a->offset, 0);
  282. else
  283. if(a->type == D_FILE1)
  284. putsymb(a->sym->name, 'Z', a->offset, 0);
  285. if(s->type == STEXT)
  286. putsymb(s->name, 'T', s->value, s->version);
  287. else
  288. putsymb(s->name, 'L', s->value, s->version);
  289. /* frame, auto and param after */
  290. putsymb(".frame", 'm', p->to.offset+8, 0);
  291. for(a=p->to.autom; a; a=a->link)
  292. if(a->type == D_AUTO)
  293. putsymb(a->sym->name, 'a', -a->offset, 0);
  294. else
  295. if(a->type == D_PARAM)
  296. putsymb(a->sym->name, 'p', a->offset, 0);
  297. }
  298. if(debug['v'] || debug['n'])
  299. Bprint(&bso, "symsize = %lud\n", symsize);
  300. Bflush(&bso);
  301. }
  302. void
  303. putsymb(char *s, int t, long v, int ver)
  304. {
  305. int i, f;
  306. if(t == 'f')
  307. s++;
  308. LPUTBE(v);
  309. if(ver)
  310. t += 'a' - 'A';
  311. CPUT(t+0x80); /* 0x80 is variable length */
  312. if(t == 'Z' || t == 'z') {
  313. CPUT(s[0]);
  314. for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
  315. CPUT(s[i]);
  316. CPUT(s[i+1]);
  317. }
  318. CPUT(0);
  319. CPUT(0);
  320. i++;
  321. }
  322. else {
  323. for(i=0; s[i]; i++)
  324. CPUT(s[i]);
  325. CPUT(0);
  326. }
  327. symsize += 4 + 1 + i + 1;
  328. if(debug['n']) {
  329. if(t == 'z' || t == 'Z') {
  330. Bprint(&bso, "%c %.8lux ", t, v);
  331. for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
  332. f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
  333. Bprint(&bso, "/%x", f);
  334. }
  335. Bprint(&bso, "\n");
  336. return;
  337. }
  338. if(ver)
  339. Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
  340. else
  341. Bprint(&bso, "%c %.8lux %s\n", t, v, s);
  342. }
  343. }
  344. #define MINLC 4
  345. void
  346. asmlc(void)
  347. {
  348. long oldpc, oldlc;
  349. Prog *p;
  350. long v, s;
  351. oldpc = INITTEXT;
  352. oldlc = 0;
  353. for(p = firstp; p != P; p = p->link) {
  354. if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
  355. if(p->as == ATEXT)
  356. curtext = p;
  357. if(debug['L'])
  358. Bprint(&bso, "%6lux %P\n",
  359. p->pc, p);
  360. continue;
  361. }
  362. if(debug['L'])
  363. Bprint(&bso, "\t\t%6ld", lcsize);
  364. v = (p->pc - oldpc) / MINLC;
  365. while(v) {
  366. s = 127;
  367. if(v < 127)
  368. s = v;
  369. CPUT(s+128); /* 129-255 +pc */
  370. if(debug['L'])
  371. Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
  372. v -= s;
  373. lcsize++;
  374. }
  375. s = p->line - oldlc;
  376. oldlc = p->line;
  377. oldpc = p->pc + MINLC;
  378. if(s > 64 || s < -64) {
  379. CPUT(0); /* 0 vv +lc */
  380. CPUT(s>>24);
  381. CPUT(s>>16);
  382. CPUT(s>>8);
  383. CPUT(s);
  384. if(debug['L']) {
  385. if(s > 0)
  386. Bprint(&bso, " lc+%ld(%d,%ld)\n",
  387. s, 0, s);
  388. else
  389. Bprint(&bso, " lc%ld(%d,%ld)\n",
  390. s, 0, s);
  391. Bprint(&bso, "%6lux %P\n",
  392. p->pc, p);
  393. }
  394. lcsize += 5;
  395. continue;
  396. }
  397. if(s > 0) {
  398. CPUT(0+s); /* 1-64 +lc */
  399. if(debug['L']) {
  400. Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
  401. Bprint(&bso, "%6lux %P\n",
  402. p->pc, p);
  403. }
  404. } else {
  405. CPUT(64-s); /* 65-128 -lc */
  406. if(debug['L']) {
  407. Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
  408. Bprint(&bso, "%6lux %P\n",
  409. p->pc, p);
  410. }
  411. }
  412. lcsize++;
  413. }
  414. while(lcsize & 1) {
  415. s = 129;
  416. CPUT(s);
  417. lcsize++;
  418. }
  419. if(debug['v'] || debug['L'])
  420. Bprint(&bso, "lcsize = %ld\n", lcsize);
  421. Bflush(&bso);
  422. }
  423. void
  424. datblk(long s, long n)
  425. {
  426. Prog *p;
  427. char *cast;
  428. long l, fl, j, d;
  429. int i, c;
  430. memset(buf.dbuf, 0, n+100);
  431. for(p = datap; p != P; p = p->link) {
  432. curp = p;
  433. l = p->from.sym->value + p->from.offset - s;
  434. c = p->reg;
  435. i = 0;
  436. if(l < 0) {
  437. if(l+c <= 0)
  438. continue;
  439. while(l < 0) {
  440. l++;
  441. i++;
  442. }
  443. }
  444. if(l >= n)
  445. continue;
  446. if(p->as != AINIT && p->as != ADYNT) {
  447. for(j=l+(c-i)-1; j>=l; j--)
  448. if(buf.dbuf[j]) {
  449. print("%P\n", p);
  450. diag("multiple initialization");
  451. break;
  452. }
  453. }
  454. switch(p->to.type) {
  455. default:
  456. diag("unknown mode in initialization\n%P", p);
  457. break;
  458. case D_FCONST:
  459. switch(c) {
  460. default:
  461. case 4:
  462. fl = ieeedtof(p->to.ieee);
  463. cast = (char*)&fl;
  464. for(; i<c; i++) {
  465. buf.dbuf[l] = cast[fnuxi8[i]];
  466. l++;
  467. }
  468. break;
  469. case 8:
  470. cast = (char*)p->to.ieee;
  471. for(; i<c; i++) {
  472. buf.dbuf[l] = cast[fnuxi8[i]];
  473. l++;
  474. }
  475. break;
  476. }
  477. break;
  478. case D_SCONST:
  479. for(; i<c; i++) {
  480. buf.dbuf[l] = p->to.sval[i];
  481. l++;
  482. }
  483. break;
  484. case D_CONST:
  485. d = p->to.offset;
  486. if(p->to.sym) {
  487. if(p->to.sym->type == STEXT ||
  488. p->to.sym->type == SLEAF)
  489. d += p->to.sym->value;
  490. if(p->to.sym->type == SDATA)
  491. d += p->to.sym->value + INITDAT;
  492. if(p->to.sym->type == SBSS)
  493. d += p->to.sym->value + INITDAT;
  494. }
  495. cast = (char*)&d;
  496. switch(c) {
  497. default:
  498. diag("bad nuxi %d %d\n%P", c, i, curp);
  499. break;
  500. case 1:
  501. for(; i<c; i++) {
  502. buf.dbuf[l] = cast[inuxi1[i]];
  503. l++;
  504. }
  505. break;
  506. case 2:
  507. for(; i<c; i++) {
  508. buf.dbuf[l] = cast[inuxi2[i]];
  509. l++;
  510. }
  511. break;
  512. case 4:
  513. for(; i<c; i++) {
  514. buf.dbuf[l] = cast[inuxi4[i]];
  515. l++;
  516. }
  517. break;
  518. case 8:
  519. for(; i<4; i++) {
  520. buf.dbuf[l] = cast[inuxi4[i]];
  521. l++;
  522. }
  523. d = p->to.offset >> 32;
  524. for(; i<c; i++) {
  525. buf.dbuf[l] = cast[inuxi4[i-4]];
  526. l++;
  527. }
  528. break;
  529. }
  530. break;
  531. }
  532. }
  533. write(cout, buf.dbuf, n);
  534. }
  535. #define OP_RRR(op,r1,r2,r3)\
  536. (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|((r3)&31L))
  537. #define OP_IRR(op,i,r2,r3)\
  538. (op|(((i)&255L)<<13)|0x1000|(((r2)&31L)<<21)|((r3)&31L))
  539. #define OP_MEM(op,d,r1,r2)\
  540. (op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|((d)&0xffff))
  541. #define OP_BR(op,d,r1)\
  542. (op|((d)&0x1fffff)|(((r1)&31L)<<21))
  543. int
  544. asmout(Prog *p, Optab *o)
  545. {
  546. long o1, o2, o3, o4, o5, o6;
  547. vlong v;
  548. int r, a;
  549. o1 = 0;
  550. o2 = 0;
  551. o3 = 0;
  552. o4 = 0;
  553. o5 = 0;
  554. o6 = 0;
  555. switch(o->type) {
  556. default:
  557. diag("unknown type %d", o->type);
  558. if(!debug['a'])
  559. prasm(p);
  560. break;
  561. case 0: /* pseudo ops */
  562. break;
  563. case 1: /* register-register moves */
  564. if(p->as == AMOVB || p->as == AMOVW) /* noop should rewrite */
  565. diag("forbidden SEX: %P", p);
  566. if(p->as == AMOVBU || p->as == AMOVWU) {
  567. v = 1;
  568. if (p->as == AMOVWU)
  569. v = 3;
  570. o1 = OP_IRR(opcode(AZAPNOT), v, p->from.reg, p->to.reg);
  571. }
  572. else {
  573. a = AOR;
  574. if(p->as == AMOVL)
  575. a = AADDL;
  576. if(p->as == AMOVLU)
  577. a = AEXTLL;
  578. o1 = OP_RRR(opcode(a), REGZERO, p->from.reg, p->to.reg);
  579. }
  580. break;
  581. case 2: /* <operate> r1,[r2],r3 */
  582. r = p->reg;
  583. if(r == NREG)
  584. r = p->to.reg;
  585. o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
  586. break;
  587. case 3: /* <operate> $n,[r2],r3 */
  588. v = regoff(&p->from);
  589. r = p->reg;
  590. if(r == NREG)
  591. r = p->to.reg;
  592. o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
  593. break;
  594. case 4: /* beq r1,sbra */
  595. if(p->cond == P)
  596. v = -4 >> 2;
  597. else
  598. v = (p->cond->pc - pc-4) >> 2;
  599. o1 = OP_BR(opcode(p->as), v, p->from.reg);
  600. break;
  601. case 5: /* jmp [r1],0(r2) */
  602. r = p->reg;
  603. a = p->as;
  604. if(r == NREG) {
  605. r = o->param;
  606. /* if(a == AJMP && p->to.reg == REGLINK)
  607. a = ARET; /* this breaks the kernel -- maybe we need to clear prediction stack on each context switch... */
  608. }
  609. o1 = OP_MEM(opcode(a), 0, p->to.reg, r);
  610. break;
  611. case 6: /* movq $n,r1 and movq $soreg,r1 */
  612. r = p->from.reg;
  613. if(r == NREG)
  614. r = o->param;
  615. v = regoff(&p->from);
  616. o1 = OP_MEM(opcode(AMOVA), v, r, p->to.reg);
  617. break;
  618. case 7: /* movbu r1, r2 */
  619. v = 1;
  620. if (p->as == AMOVWU)
  621. v = 3;
  622. o1 = OP_IRR(opcode(AZAPNOT), v, p->from.reg, p->to.reg);
  623. break;
  624. case 8: /* mov r, soreg ==> stq o(r) */
  625. r = p->to.reg;
  626. if(r == NREG)
  627. r = o->param;
  628. v = regoff(&p->to);
  629. if (p->as == AMOVQ || p->as == AMOVT)
  630. if ((r == REGSP || r == REGSB) && (v&7) != 0)
  631. diag("bad alignment: %P", p);
  632. o1 = OP_MEM(opcode(p->as+AEND), v, r, p->from.reg);
  633. break;
  634. case 9: /* mov soreg, r ==> ldq o(r) */
  635. r = p->from.reg;
  636. if(r == NREG)
  637. r = o->param;
  638. v = regoff(&p->from);
  639. if (p->as == AMOVQ || p->as == AMOVT)
  640. if ((r == REGSP || r == REGSB) && (v&7) != 0)
  641. diag("bad alignment: %P", p);
  642. o1 = OP_MEM(opcode(p->as), v, r, p->to.reg);
  643. break;
  644. case 10: /* movb r1,r2 */
  645. v = 64 - 8;
  646. if (p->as == AMOVW)
  647. v = 64 - 16;
  648. o1 = OP_IRR(opcode(ASLLQ), v, p->from.reg, p->to.reg);
  649. o2 = OP_IRR(opcode(ASRAQ), v, p->to.reg, p->to.reg);
  650. break;
  651. case 11: /* jmp lbra */
  652. if(p->cond == P)
  653. v = -4 >> 2;
  654. else
  655. v = (p->cond->pc - pc-4) >> 2;
  656. a = ABR;
  657. r = REGZERO;
  658. if (p->as == AJSR) {
  659. a = ABSR;
  660. r = REGLINK;
  661. }
  662. o1 = OP_BR(opcode(a), v, r);
  663. break;
  664. case 12: /* addq $n,[r2],r3 ==> lda */
  665. v = regoff(&p->from);
  666. if (p->as == ASUBQ)
  667. v = -v;
  668. r = p->reg;
  669. if(r == NREG)
  670. r = p->to.reg;
  671. o1 = OP_MEM(opcode(AMOVA), v, r, p->to.reg);
  672. break;
  673. case 13: /* <op> $scon,[r2],r3 */
  674. v = regoff(&p->from);
  675. if(p->to.reg == REGTMP || p->reg == REGTMP)
  676. diag("cant synthesize large constant\n%P", p);
  677. r = p->reg;
  678. if(r == NREG)
  679. r = p->to.reg;
  680. o1 = OP_MEM(opcode(AMOVA), v, REGZERO, REGTMP);
  681. o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
  682. break;
  683. case 14: /* <op> $lcon,[r2],r3 */
  684. v = regoff(&p->from);
  685. if(v & 0x8000)
  686. v += 0x10000;
  687. if(p->to.reg == REGTMP || p->reg == REGTMP)
  688. diag("cant synthesize large constant\n%P", p);
  689. r = p->reg;
  690. if(r == NREG)
  691. r = p->to.reg;
  692. o1 = OP_MEM(opcode(AMOVA), v, REGZERO, REGTMP);
  693. o2 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
  694. o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
  695. break;
  696. case 15: /* mov $lcon,r1 */
  697. v = regoff(&p->from);
  698. if(v & 0x8000)
  699. v += 0x10000;
  700. o1 = OP_MEM(opcode(AMOVA), v, o->param, REGTMP);
  701. o2 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, p->to.reg);
  702. break;
  703. case 16: /* mov $qcon,r1 */
  704. v = regoff(&p->from);
  705. if(v & 0x8000)
  706. v += 0x10000;
  707. if((v>>31)&1)
  708. v += (1LL<<32);
  709. if((v>>47)&1)
  710. v += (1LL<<48);
  711. o1 = OP_MEM(opcode(AMOVA), v>>32, o->param, REGTMP);
  712. o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
  713. o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
  714. o4 = OP_MEM(opcode(AMOVA), v, REGTMP, REGTMP);
  715. o5 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, p->to.reg);
  716. break;
  717. case 17: /* mov f1,f2 ==> fcpys f1,f1,f2 */
  718. o1 = OP_RRR(opcode(ACPYS), p->from.reg, p->from.reg, p->to.reg);
  719. break;
  720. case 18: /* call_pal imm */
  721. v = regoff(&p->from);
  722. o1 = OP_MEM(opcode(ACALL_PAL), v, 0, 0);
  723. break;
  724. case 19: /* mov r, loreg ==> ldah,stq */
  725. r = p->to.reg;
  726. if(r == NREG)
  727. r = o->param;
  728. v = regoff(&p->to);
  729. if (p->as == AMOVQ || p->as == AMOVT)
  730. if ((r == REGSP || r == REGSB) && (v&7) != 0)
  731. diag("bad alignment: %P", p);
  732. if(v & 0x8000)
  733. v += 0x10000;
  734. o1 = OP_MEM(opcode(AMOVAH), v>>16, r, REGTMP);
  735. o2 = OP_MEM(opcode(p->as+AEND), v, REGTMP, p->from.reg);
  736. break;
  737. case 20: /* mov loreg, r ==> ldah,ldq */
  738. r = p->from.reg;
  739. if(r == NREG)
  740. r = o->param;
  741. v = regoff(&p->from);
  742. if (p->as == AMOVQ || p->as == AMOVT)
  743. if ((r == REGSP || r == REGSB) && (v&7) != 0)
  744. diag("bad alignment: %P", p);
  745. if(v & 0x8000)
  746. v += 0x10000;
  747. o1 = OP_MEM(opcode(AMOVAH), v>>16, r, REGTMP);
  748. o2 = OP_MEM(opcode(p->as), v, REGTMP, p->to.reg);
  749. break;
  750. #ifdef NEVER
  751. case 21: /* mov r1,$qoreg */
  752. r = p->to.reg;
  753. if(r == NREG)
  754. r = o->param;
  755. v = regoff(&p->to);
  756. if(v & 0x8000)
  757. v += 0x10000;
  758. if((v>>31)&1)
  759. v += (1LL<<32);
  760. if((v>>47)&1)
  761. v += (1LL<<48);
  762. o1 = OP_MEM(opcode(AMOVA), v>>32, r, REGTMP);
  763. o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
  764. o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
  765. o4 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
  766. o5 = OP_MEM(opcode(p->as+AEND), v, REGTMP, p->from.reg);
  767. break;
  768. case 22: /* mov $qoreg,r1 */
  769. r = p->from.reg;
  770. if(r == NREG)
  771. r = o->param;
  772. v = regoff(&p->from);
  773. if(v & 0x8000)
  774. v += 0x10000;
  775. if((v>>31)&1)
  776. v += (1LL<<32);
  777. if((v>>47)&1)
  778. v += (1LL<<48);
  779. o1 = OP_MEM(opcode(AMOVA), v>>32, r, REGTMP);
  780. o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
  781. o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
  782. o4 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
  783. o5 = OP_MEM(opcode(p->as), v, REGTMP, p->to.reg);
  784. break;
  785. #endif
  786. case 23: /* <op> $qcon,r1 */
  787. if(p->to.reg == REGTMP || p->reg == REGTMP)
  788. diag("cant synthesize large constant\n%P", p);
  789. v = regoff(&p->from);
  790. r = p->reg;
  791. if(r == NREG)
  792. r = p->to.reg;
  793. if(v & 0x8000)
  794. v += 0x10000;
  795. if((v>>31)&1)
  796. v += (1LL<<32);
  797. if((v>>47)&1)
  798. v += (1LL<<48);
  799. o1 = OP_MEM(opcode(AMOVA), v>>32, REGZERO, REGTMP);
  800. o2 = OP_MEM(opcode(AMOVAH), v>>48, REGTMP, REGTMP);
  801. o3 = OP_IRR(opcode(ASLLQ), 32, REGTMP, REGTMP);
  802. o4 = OP_MEM(opcode(AMOVA), v, REGTMP, REGTMP);
  803. o5 = OP_MEM(opcode(AMOVAH), v>>16, REGTMP, REGTMP);
  804. o6 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
  805. break;
  806. case 24: /* movq Fn, FPCR */
  807. r = p->from.reg;
  808. o1 = OP_RRR(opcode(AADDT+AEND), r, r, r);
  809. break;
  810. case 25: /* movq FPCR, Fn */
  811. r = p->to.reg;
  812. o1 = OP_RRR(opcode(AADDS+AEND), r, r, r);
  813. break;
  814. case 26: /* movq Rn, C_PREG */
  815. r = p->from.reg;
  816. o1 = OP_RRR(opcode(ASUBQ+AEND), r, r, 0) | p->to.reg & 255;
  817. break;
  818. case 27: /* movq C_PREG, Rn */
  819. r = p->to.reg;
  820. o1 = OP_RRR(opcode(AADDQ+AEND), r, r, 0) | p->from.reg & 255;
  821. break;
  822. case 28: /* cvttq r1,r3 */
  823. r = p->from.reg;
  824. o1 = OP_RRR(opcode(p->as), r, REGZERO, p->to.reg);
  825. break;
  826. case 29: /* movq pcc, rpcc -> Rn */
  827. o1 = OP_MEM(opcode(ARPCC), 0, REGZERO, p->to.reg);
  828. break;
  829. case 30: /* rei/mb/trapb */
  830. o1 = OP_MEM(opcode(p->as), 0, REGZERO, REGZERO);
  831. break;
  832. case 31: /* fetch (Rn) */
  833. o1 = OP_MEM(opcode(p->as), 0, REGZERO, p->from.reg);
  834. break;
  835. case 32: /* movqp r, soreg ==> stqp o(r) */
  836. r = p->to.reg;
  837. if(r == NREG)
  838. r = o->param;
  839. v = regoff(&p->to);
  840. if (v < -0x800 || v >= 0x800)
  841. diag("physical store out of range\n%P", p);
  842. v &= 0xfff;
  843. o1 = OP_MEM(opcode(p->as+AEND), v, r, p->from.reg);
  844. break;
  845. case 33: /* movqp soreg, r ==> ldqp o(r) */
  846. r = p->from.reg;
  847. if(r == NREG)
  848. r = o->param;
  849. v = regoff(&p->from);
  850. if (v < -0x800 || v >= 0x800)
  851. diag("physical load out of range\n%P", p);
  852. v &= 0xfff;
  853. o1 = OP_MEM(opcode(p->as), v, r, p->to.reg);
  854. break;
  855. case 34: /* <operate> $-n,[r2],r3 */
  856. v = regoff(&p->from);
  857. r = p->reg;
  858. if(r == NREG)
  859. r = p->to.reg;
  860. switch (a = p->as) {
  861. case AAND:
  862. a = AANDNOT;
  863. break;
  864. case AANDNOT:
  865. a = AAND;
  866. break;
  867. case AOR:
  868. a = AORNOT;
  869. break;
  870. case AORNOT:
  871. a = AOR;
  872. break;
  873. case AXOR:
  874. a = AXORNOT;
  875. break;
  876. case AXORNOT:
  877. a = AXOR;
  878. break;
  879. default:
  880. diag("bad in NCON case: %P", p);
  881. }
  882. v = ~v;
  883. o1 = OP_IRR(opcode(a), v, r, p->to.reg);
  884. break;
  885. case 40: /* word */
  886. o1 = regoff(&p->to);
  887. break;
  888. }
  889. switch(o->size) {
  890. default:
  891. if(debug['a'])
  892. Bprint(&bso, " %.8lux:\t\t%P\n", p->pc, p);
  893. break;
  894. case 4:
  895. if(debug['a'])
  896. Bprint(&bso, " %.8lux: %.8lux\t%P\n", p->pc, o1, p);
  897. LPUT(o1);
  898. break;
  899. case 8:
  900. if(debug['a'])
  901. Bprint(&bso, " %.8lux: %.8lux %.8lux %P\n", p->pc, o1, o2, p);
  902. LPUT(o1);
  903. LPUT(o2);
  904. break;
  905. case 12:
  906. if(debug['a'])
  907. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %P\n", p->pc, o1, o2, o3, p);
  908. LPUT(o1);
  909. LPUT(o2);
  910. LPUT(o3);
  911. break;
  912. case 16:
  913. if(debug['a'])
  914. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %P\n",
  915. p->pc, o1, o2, o3, o4, p);
  916. LPUT(o1);
  917. LPUT(o2);
  918. LPUT(o3);
  919. LPUT(o4);
  920. break;
  921. case 20:
  922. if(debug['a'])
  923. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %P\n",
  924. p->pc, o1, o2, o3, o4, o5, p);
  925. LPUT(o1);
  926. LPUT(o2);
  927. LPUT(o3);
  928. LPUT(o4);
  929. LPUT(o5);
  930. break;
  931. case 24:
  932. if(debug['a'])
  933. Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %P\n",
  934. p->pc, o1, o2, o3, o4, o5, o6, p);
  935. LPUT(o1);
  936. LPUT(o2);
  937. LPUT(o3);
  938. LPUT(o4);
  939. LPUT(o5);
  940. LPUT(o6);
  941. break;
  942. }
  943. return 0;
  944. }
  945. #define OP(x,y) (((x)<<26)|((y)<<5))
  946. #define FP(x) OP(22, (x)|0xc0) /* note: this sets round/trap modes (dynamic, software?). not used for cvtxx? */
  947. #define FP2(x) OP(22, (x) /*|0x080*/) /* note: this sets round/trap modes (chopped, software?). used for cvtxx? */
  948. #define FP3(x) OP(22, (x)|0x080) /* note: this sets round/trap modes (dynamic, software?). not used for cvtxx? */
  949. long
  950. opcode(int a)
  951. {
  952. switch (a) {
  953. /* loads */
  954. case AMOVB: /* misnomer; pretend it's ok for now */
  955. diag("opcode(AMOVB)");
  956. case AMOVBU: return OP(10, 0); /* v 3 */
  957. case AMOVW: /* misnomer; pretend it's ok for now */
  958. diag("opcode(AMOVW)");
  959. case AMOVWU: return OP(12, 0); /* v 3 */
  960. case AMOVL: return OP(40, 0);
  961. case AMOVQ: return OP(41, 0);
  962. case AMOVQU: return OP(11, 0);
  963. case AMOVS: return OP(34, 0);
  964. case AMOVT: return OP(35, 0);
  965. /* stores */
  966. case AMOVB+AEND: /* misnomer; pretend it's ok for now */
  967. case AMOVBU+AEND: return OP(14, 0); /* v 3 */
  968. case AMOVW+AEND: /* misnomer; pretend it's ok for now */
  969. case AMOVWU+AEND: return OP(13, 0); /* v 3 */
  970. case AMOVL+AEND: return OP(44, 0);
  971. case AMOVQ+AEND: return OP(45, 0);
  972. case AMOVQU+AEND: return OP(15, 0);
  973. case AMOVS+AEND: return OP(38, 0);
  974. case AMOVT+AEND: return OP(39, 0);
  975. /* physical */
  976. case AMOVLP+AEND: return OP(31, 0)|0x8000;
  977. case AMOVQP+AEND: return OP(31, 0)|0x9000;
  978. case AMOVLP: return OP(27, 0)|0x8000;
  979. case AMOVQP: return OP(27, 0)|0x9000;
  980. /* load address */
  981. case AMOVA: return OP(8, 0);
  982. case AMOVAH: return OP(9, 0);
  983. /* locking */
  984. case AMOVLL: return OP(42, 0); /* load locked */
  985. case AMOVQL: return OP(43, 0); /* load locked */
  986. case AMOVLC+AEND: return OP(46, 0); /* store cond */
  987. case AMOVQC+AEND: return OP(47, 0); /* store cond */
  988. case AADDL: return OP(16, 0);
  989. case AADDLV: return OP(16, 64);
  990. case AADDQ: return OP(16, 32);
  991. case AADDQV: return OP(16, 96);
  992. case AS4ADDL: return OP(16, 2);
  993. case AS4ADDQ: return OP(16, 34);
  994. case AS8ADDL: return OP(16, 18);
  995. case AS8ADDQ: return OP(16, 50);
  996. case AS4SUBL: return OP(16, 11);
  997. case AS4SUBQ: return OP(16, 43);
  998. case AS8SUBL: return OP(16, 27);
  999. case AS8SUBQ: return OP(16, 59);
  1000. case ASUBL: return OP(16, 9);
  1001. case ASUBLV: return OP(16, 73);
  1002. case ASUBQ: return OP(16, 41);
  1003. case ASUBQV: return OP(16, 105);
  1004. case ACMPEQ: return OP(16, 45);
  1005. case ACMPGT: return OP(16, 77);
  1006. case ACMPGE: return OP(16, 109);
  1007. case ACMPUGT: return OP(16, 29);
  1008. case ACMPUGE: return OP(16, 61);
  1009. case ACMPBLE: return OP(16, 15);
  1010. case AAND: return OP(17, 0);
  1011. case AANDNOT: return OP(17, 8);
  1012. case AOR: return OP(17, 32);
  1013. case AORNOT: return OP(17, 40);
  1014. case AXOR: return OP(17, 64);
  1015. case AXORNOT: return OP(17, 72);
  1016. case ACMOVEQ: return OP(17, 36);
  1017. case ACMOVNE: return OP(17, 38);
  1018. case ACMOVLT: return OP(17, 68);
  1019. case ACMOVGE: return OP(17, 70);
  1020. case ACMOVLE: return OP(17, 100);
  1021. case ACMOVGT: return OP(17, 102);
  1022. case ACMOVLBS: return OP(17, 20);
  1023. case ACMOVLBC: return OP(17, 22);
  1024. case AMULL: return OP(19, 0);
  1025. case AMULQ: return OP(19, 32);
  1026. case AMULLV: return OP(19, 64);
  1027. case AMULQV: return OP(19, 96);
  1028. case AUMULH: return OP(19, 48);
  1029. case ASLLQ: return OP(18, 57);
  1030. case ASRLQ: return OP(18, 52);
  1031. case ASRAQ: return OP(18, 60);
  1032. case AEXTBL: return OP(18, 6);
  1033. case AEXTWL: return OP(18, 22);
  1034. case AEXTLL: return OP(18, 38);
  1035. case AEXTQL: return OP(18, 54);
  1036. case AEXTWH: return OP(18, 90);
  1037. case AEXTLH: return OP(18, 106);
  1038. case AEXTQH: return OP(18, 122);
  1039. case AINSBL: return OP(18, 11);
  1040. case AINSWL: return OP(18, 27);
  1041. case AINSLL: return OP(18, 43);
  1042. case AINSQL: return OP(18, 59);
  1043. case AINSWH: return OP(18, 87);
  1044. case AINSLH: return OP(18, 103);
  1045. case AINSQH: return OP(18, 119);
  1046. case AMSKBL: return OP(18, 2);
  1047. case AMSKWL: return OP(18, 18);
  1048. case AMSKLL: return OP(18, 34);
  1049. case AMSKQL: return OP(18, 50);
  1050. case AMSKWH: return OP(18, 82);
  1051. case AMSKLH: return OP(18, 98);
  1052. case AMSKQH: return OP(18, 114);
  1053. case AZAP: return OP(18, 48);
  1054. case AZAPNOT: return OP(18, 49);
  1055. case AJMP: return OP(26, 0);
  1056. case AJSR: return OP(26, 512);
  1057. case ARET: return OP(26, 1024);
  1058. case ABR: return OP(48, 0);
  1059. case ABSR: return OP(52, 0);
  1060. case ABEQ: return OP(57, 0);
  1061. case ABNE: return OP(61, 0);
  1062. case ABLT: return OP(58, 0);
  1063. case ABGE: return OP(62, 0);
  1064. case ABLE: return OP(59, 0);
  1065. case ABGT: return OP(63, 0);
  1066. case ABLBC: return OP(56, 0);
  1067. case ABLBS: return OP(60, 0);
  1068. case AFBEQ: return OP(49, 0);
  1069. case AFBNE: return OP(53, 0);
  1070. case AFBLT: return OP(50, 0);
  1071. case AFBGE: return OP(54, 0);
  1072. case AFBLE: return OP(51, 0);
  1073. case AFBGT: return OP(55, 0);
  1074. case ATRAPB: return OP(24, 0);
  1075. case AMB: return OP(24, 0x200);
  1076. case AFETCH: return OP(24, 0x400);
  1077. case AFETCHM: return OP(24, 0x500);
  1078. case ARPCC: return OP(24, 0x600);
  1079. case ACPYS: return OP(23, 32);
  1080. case ACPYSN: return OP(23, 33);
  1081. case ACPYSE: return OP(23, 34);
  1082. case AADDS+AEND: return OP(23, 37); /* MF_FPCR */
  1083. case AADDT+AEND: return OP(23, 36); /* MT_FPCR */
  1084. case ACVTLQ: return OP(23, 16);
  1085. case ACVTQL: return OP(23, 48); /* XXX trap mode */
  1086. case AFCMOVEQ: return OP(23, 42);
  1087. case AFCMOVNE: return OP(23, 43);
  1088. case AFCMOVLT: return OP(23, 44);
  1089. case AFCMOVGE: return OP(23, 45);
  1090. case AFCMOVLE: return OP(23, 46);
  1091. case AFCMOVGT: return OP(23, 47);
  1092. case AADDS: return FP(0);
  1093. case AADDT: return FP(32);
  1094. case ACMPTEQ: return FP3(37);
  1095. case ACMPTGT: return FP3(38);
  1096. case ACMPTGE: return FP3(39);
  1097. case ACMPTUN: return FP3(36);
  1098. case ACVTQS: return FP2(60);
  1099. case ACVTQT: return FP2(62);
  1100. case ACVTTS: return FP2(44);
  1101. case ACVTTQ: return FP2(47);
  1102. case ADIVS: return FP(3);
  1103. case ADIVT: return FP(35);
  1104. case AMULS: return FP(2);
  1105. case AMULT: return FP(34);
  1106. case ASUBS: return FP(1);
  1107. case ASUBT: return FP(33);
  1108. case ACALL_PAL: return 0;
  1109. case AREI: return OP(30, 0x400); /* HW_REI */
  1110. case AADDQ+AEND: return OP(25,0); /* HW_MFPR */
  1111. case ASUBQ+AEND: return OP(29,0); /* HW_MTPR */
  1112. }
  1113. diag("bad op %A(%d)", a, a);
  1114. return 0;
  1115. }