PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/utils/6l/span.c

https://bitbucket.org/floren/inferno/
C | 1746 lines | 1547 code | 159 blank | 40 comment | 347 complexity | b2cf7557b2eb0d378095d1a8059d03ed MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. #include "l.h"
  2. static int rexflag;
  3. static int asmode;
  4. void
  5. span(void)
  6. {
  7. Prog *p, *q;
  8. long v;
  9. vlong c, idat;
  10. int m, n, again;
  11. xdefine("etext", STEXT, 0L);
  12. idat = INITDAT;
  13. for(p = firstp; p != P; p = p->link) {
  14. if(p->as == ATEXT)
  15. curtext = p;
  16. n = 0;
  17. if(p->to.type == D_BRANCH)
  18. if(p->pcond == P)
  19. p->pcond = p;
  20. if((q = p->pcond) != P)
  21. if(q->back != 2)
  22. n = 1;
  23. p->back = n;
  24. if(p->as == AADJSP) {
  25. p->to.type = D_SP;
  26. v = -p->from.offset;
  27. p->from.offset = v;
  28. p->as = p->mode != 64? AADDL: AADDQ;
  29. if(v < 0) {
  30. p->as = p->mode != 64? ASUBL: ASUBQ;
  31. v = -v;
  32. p->from.offset = v;
  33. }
  34. if(v == 0)
  35. p->as = ANOP;
  36. }
  37. }
  38. n = 0;
  39. start:
  40. if(debug['v'])
  41. Bprint(&bso, "%5.2f span\n", cputime());
  42. Bflush(&bso);
  43. c = INITTEXT;
  44. for(p = firstp; p != P; p = p->link) {
  45. if(p->as == ATEXT)
  46. curtext = p;
  47. if(p->to.type == D_BRANCH)
  48. if(p->back)
  49. p->pc = c;
  50. asmins(p);
  51. p->pc = c;
  52. m = andptr-and;
  53. p->mark = m;
  54. c += m;
  55. }
  56. loop:
  57. n++;
  58. if(debug['v'])
  59. Bprint(&bso, "%5.2f span %d\n", cputime(), n);
  60. Bflush(&bso);
  61. if(n > 50) {
  62. print("span must be looping\n");
  63. errorexit();
  64. }
  65. again = 0;
  66. c = INITTEXT;
  67. for(p = firstp; p != P; p = p->link) {
  68. if(p->as == ATEXT)
  69. curtext = p;
  70. if(p->to.type == D_BRANCH || p->back & 0100) {
  71. if(p->back)
  72. p->pc = c;
  73. asmins(p);
  74. m = andptr-and;
  75. if(m != p->mark) {
  76. p->mark = m;
  77. again++;
  78. }
  79. }
  80. p->pc = c;
  81. c += p->mark;
  82. }
  83. if(again) {
  84. textsize = c;
  85. goto loop;
  86. }
  87. if(INITRND) {
  88. INITDAT = rnd(c, INITRND);
  89. if(INITDAT != idat) {
  90. idat = INITDAT;
  91. goto start;
  92. }
  93. }
  94. xdefine("etext", STEXT, c);
  95. if(debug['v'])
  96. Bprint(&bso, "etext = %llux\n", c);
  97. Bflush(&bso);
  98. for(p = textp; p != P; p = p->pcond)
  99. p->from.sym->value = p->pc;
  100. textsize = c - INITTEXT;
  101. }
  102. void
  103. xdefine(char *p, int t, vlong v)
  104. {
  105. Sym *s;
  106. s = lookup(p, 0);
  107. if(s->type == 0 || s->type == SXREF) {
  108. s->type = t;
  109. s->value = v;
  110. }
  111. if(s->type == STEXT && s->value == 0)
  112. s->value = v;
  113. }
  114. void
  115. putsymb(char *s, int t, vlong v, int ver)
  116. {
  117. int i, f, l;
  118. if(t == 'f')
  119. s++;
  120. l = 4;
  121. if(!debug['8']){
  122. lput(v>>32);
  123. l = 8;
  124. }
  125. lput(v);
  126. if(ver)
  127. t += 'a' - 'A';
  128. cput(t+0x80); /* 0x80 is variable length */
  129. if(t == 'Z' || t == 'z') {
  130. cput(s[0]);
  131. for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
  132. cput(s[i]);
  133. cput(s[i+1]);
  134. }
  135. cput(0);
  136. cput(0);
  137. i++;
  138. }
  139. else {
  140. for(i=0; s[i]; i++)
  141. cput(s[i]);
  142. cput(0);
  143. }
  144. symsize += l + 1 + i + 1;
  145. if(debug['n']) {
  146. if(t == 'z' || t == 'Z') {
  147. Bprint(&bso, "%c %.8llux ", t, v);
  148. for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
  149. f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
  150. Bprint(&bso, "/%x", f);
  151. }
  152. Bprint(&bso, "\n");
  153. return;
  154. }
  155. if(ver)
  156. Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
  157. else
  158. Bprint(&bso, "%c %.8llux %s\n", t, v, s);
  159. }
  160. }
  161. void
  162. asmsym(void)
  163. {
  164. Prog *p;
  165. Auto *a;
  166. Sym *s;
  167. int h;
  168. s = lookup("etext", 0);
  169. if(s->type == STEXT)
  170. putsymb(s->name, 'T', s->value, s->version);
  171. for(h=0; h<NHASH; h++)
  172. for(s=hash[h]; s!=S; s=s->link)
  173. switch(s->type) {
  174. case SCONST:
  175. putsymb(s->name, 'D', s->value, s->version);
  176. continue;
  177. case SDATA:
  178. putsymb(s->name, 'D', s->value+INITDAT, s->version);
  179. continue;
  180. case SBSS:
  181. putsymb(s->name, 'B', s->value+INITDAT, s->version);
  182. continue;
  183. case SFILE:
  184. putsymb(s->name, 'f', s->value, s->version);
  185. continue;
  186. }
  187. for(p=textp; p!=P; p=p->pcond) {
  188. s = p->from.sym;
  189. if(s->type != STEXT)
  190. continue;
  191. /* filenames first */
  192. for(a=p->to.autom; a; a=a->link)
  193. if(a->type == D_FILE)
  194. putsymb(a->asym->name, 'z', a->aoffset, 0);
  195. else
  196. if(a->type == D_FILE1)
  197. putsymb(a->asym->name, 'Z', a->aoffset, 0);
  198. putsymb(s->name, 'T', s->value, s->version);
  199. /* frame, auto and param after */
  200. putsymb(".frame", 'm', p->to.offset+8, 0);
  201. for(a=p->to.autom; a; a=a->link)
  202. if(a->type == D_AUTO)
  203. putsymb(a->asym->name, 'a', -a->aoffset, 0);
  204. else
  205. if(a->type == D_PARAM)
  206. putsymb(a->asym->name, 'p', a->aoffset, 0);
  207. }
  208. if(debug['v'] || debug['n'])
  209. Bprint(&bso, "symsize = %lud\n", symsize);
  210. Bflush(&bso);
  211. }
  212. void
  213. asmlc(void)
  214. {
  215. vlong oldpc;
  216. Prog *p;
  217. long oldlc, v, s;
  218. oldpc = INITTEXT;
  219. oldlc = 0;
  220. for(p = firstp; p != P; p = p->link) {
  221. if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
  222. if(p->as == ATEXT)
  223. curtext = p;
  224. if(debug['L'])
  225. Bprint(&bso, "%6llux %P\n",
  226. p->pc, p);
  227. continue;
  228. }
  229. if(debug['L'])
  230. Bprint(&bso, "\t\t%6ld", lcsize);
  231. v = (p->pc - oldpc) / MINLC;
  232. while(v) {
  233. s = 127;
  234. if(v < 127)
  235. s = v;
  236. cput(s+128); /* 129-255 +pc */
  237. if(debug['L'])
  238. Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
  239. v -= s;
  240. lcsize++;
  241. }
  242. s = p->line - oldlc;
  243. oldlc = p->line;
  244. oldpc = p->pc + MINLC;
  245. if(s > 64 || s < -64) {
  246. cput(0); /* 0 vv +lc */
  247. cput(s>>24);
  248. cput(s>>16);
  249. cput(s>>8);
  250. cput(s);
  251. if(debug['L']) {
  252. if(s > 0)
  253. Bprint(&bso, " lc+%ld(%d,%ld)\n",
  254. s, 0, s);
  255. else
  256. Bprint(&bso, " lc%ld(%d,%ld)\n",
  257. s, 0, s);
  258. Bprint(&bso, "%6llux %P\n",
  259. p->pc, p);
  260. }
  261. lcsize += 5;
  262. continue;
  263. }
  264. if(s > 0) {
  265. cput(0+s); /* 1-64 +lc */
  266. if(debug['L']) {
  267. Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
  268. Bprint(&bso, "%6llux %P\n",
  269. p->pc, p);
  270. }
  271. } else {
  272. cput(64-s); /* 65-128 -lc */
  273. if(debug['L']) {
  274. Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
  275. Bprint(&bso, "%6llux %P\n",
  276. p->pc, p);
  277. }
  278. }
  279. lcsize++;
  280. }
  281. while(lcsize & 1) {
  282. s = 129;
  283. cput(s);
  284. lcsize++;
  285. }
  286. if(debug['v'] || debug['L'])
  287. Bprint(&bso, "lcsize = %ld\n", lcsize);
  288. Bflush(&bso);
  289. }
  290. int
  291. oclass(Adr *a)
  292. {
  293. vlong v;
  294. long l;
  295. if(a->type >= D_INDIR || a->index != D_NONE) {
  296. if(a->index != D_NONE && a->scale == 0) {
  297. if(a->type == D_ADDR) {
  298. switch(a->index) {
  299. case D_EXTERN:
  300. case D_STATIC:
  301. return Yi32; /* TO DO: Yi64 */
  302. case D_AUTO:
  303. case D_PARAM:
  304. return Yiauto;
  305. }
  306. return Yxxx;
  307. }
  308. return Ycol;
  309. }
  310. return Ym;
  311. }
  312. switch(a->type)
  313. {
  314. case D_AL:
  315. return Yal;
  316. case D_AX:
  317. return Yax;
  318. /*
  319. case D_SPB:
  320. */
  321. case D_BPB:
  322. case D_SIB:
  323. case D_DIB:
  324. case D_R8B:
  325. case D_R9B:
  326. case D_R10B:
  327. case D_R11B:
  328. case D_R12B:
  329. case D_R13B:
  330. case D_R14B:
  331. case D_R15B:
  332. if(asmode != 64)
  333. return Yxxx;
  334. case D_DL:
  335. case D_BL:
  336. case D_AH:
  337. case D_CH:
  338. case D_DH:
  339. case D_BH:
  340. return Yrb;
  341. case D_CL:
  342. return Ycl;
  343. case D_CX:
  344. return Ycx;
  345. case D_DX:
  346. case D_BX:
  347. return Yrx;
  348. case D_R8: /* not really Yrl */
  349. case D_R9:
  350. case D_R10:
  351. case D_R11:
  352. case D_R12:
  353. case D_R13:
  354. case D_R14:
  355. case D_R15:
  356. if(asmode != 64)
  357. return Yxxx;
  358. case D_SP:
  359. case D_BP:
  360. case D_SI:
  361. case D_DI:
  362. return Yrl;
  363. case D_F0+0:
  364. return Yf0;
  365. case D_F0+1:
  366. case D_F0+2:
  367. case D_F0+3:
  368. case D_F0+4:
  369. case D_F0+5:
  370. case D_F0+6:
  371. case D_F0+7:
  372. return Yrf;
  373. case D_M0+0:
  374. case D_M0+1:
  375. case D_M0+2:
  376. case D_M0+3:
  377. case D_M0+4:
  378. case D_M0+5:
  379. case D_M0+6:
  380. case D_M0+7:
  381. return Ymr;
  382. case D_X0+0:
  383. case D_X0+1:
  384. case D_X0+2:
  385. case D_X0+3:
  386. case D_X0+4:
  387. case D_X0+5:
  388. case D_X0+6:
  389. case D_X0+7:
  390. case D_X0+8:
  391. case D_X0+9:
  392. case D_X0+10:
  393. case D_X0+11:
  394. case D_X0+12:
  395. case D_X0+13:
  396. case D_X0+14:
  397. case D_X0+15:
  398. return Yxr;
  399. case D_NONE:
  400. return Ynone;
  401. case D_CS: return Ycs;
  402. case D_SS: return Yss;
  403. case D_DS: return Yds;
  404. case D_ES: return Yes;
  405. case D_FS: return Yfs;
  406. case D_GS: return Ygs;
  407. case D_GDTR: return Ygdtr;
  408. case D_IDTR: return Yidtr;
  409. case D_LDTR: return Yldtr;
  410. case D_MSW: return Ymsw;
  411. case D_TASK: return Ytask;
  412. case D_CR+0: return Ycr0;
  413. case D_CR+1: return Ycr1;
  414. case D_CR+2: return Ycr2;
  415. case D_CR+3: return Ycr3;
  416. case D_CR+4: return Ycr4;
  417. case D_CR+5: return Ycr5;
  418. case D_CR+6: return Ycr6;
  419. case D_CR+7: return Ycr7;
  420. case D_CR+8: return Ycr8;
  421. case D_DR+0: return Ydr0;
  422. case D_DR+1: return Ydr1;
  423. case D_DR+2: return Ydr2;
  424. case D_DR+3: return Ydr3;
  425. case D_DR+4: return Ydr4;
  426. case D_DR+5: return Ydr5;
  427. case D_DR+6: return Ydr6;
  428. case D_DR+7: return Ydr7;
  429. case D_TR+0: return Ytr0;
  430. case D_TR+1: return Ytr1;
  431. case D_TR+2: return Ytr2;
  432. case D_TR+3: return Ytr3;
  433. case D_TR+4: return Ytr4;
  434. case D_TR+5: return Ytr5;
  435. case D_TR+6: return Ytr6;
  436. case D_TR+7: return Ytr7;
  437. case D_EXTERN:
  438. case D_STATIC:
  439. case D_AUTO:
  440. case D_PARAM:
  441. return Ym;
  442. case D_CONST:
  443. case D_ADDR:
  444. if(a->sym == S) {
  445. v = a->offset;
  446. if(v == 0)
  447. return Yi0;
  448. if(v == 1)
  449. return Yi1;
  450. if(v >= -128 && v <= 127)
  451. return Yi8;
  452. l = v;
  453. if((vlong)l == v)
  454. return Ys32; /* can sign extend */
  455. if((v>>32) == 0)
  456. return Yi32; /* unsigned */
  457. return Yi64;
  458. }
  459. return Yi32; /* TO DO: D_ADDR as Yi64 */
  460. case D_BRANCH:
  461. return Ybr;
  462. }
  463. return Yxxx;
  464. }
  465. void
  466. asmidx(Adr *a, int base)
  467. {
  468. int i;
  469. switch(a->index) {
  470. default:
  471. goto bad;
  472. case D_NONE:
  473. i = 4 << 3;
  474. goto bas;
  475. case D_R8:
  476. case D_R9:
  477. case D_R10:
  478. case D_R11:
  479. case D_R12:
  480. case D_R13:
  481. case D_R14:
  482. case D_R15:
  483. if(asmode != 64)
  484. goto bad;
  485. case D_AX:
  486. case D_CX:
  487. case D_DX:
  488. case D_BX:
  489. case D_BP:
  490. case D_SI:
  491. case D_DI:
  492. i = reg[a->index] << 3;
  493. break;
  494. }
  495. switch(a->scale) {
  496. default:
  497. goto bad;
  498. case 1:
  499. break;
  500. case 2:
  501. i |= (1<<6);
  502. break;
  503. case 4:
  504. i |= (2<<6);
  505. break;
  506. case 8:
  507. i |= (3<<6);
  508. break;
  509. }
  510. bas:
  511. switch(base) {
  512. default:
  513. goto bad;
  514. case D_NONE: /* must be mod=00 */
  515. i |= 5;
  516. break;
  517. case D_R8:
  518. case D_R9:
  519. case D_R10:
  520. case D_R11:
  521. case D_R12:
  522. case D_R13:
  523. case D_R14:
  524. case D_R15:
  525. if(asmode != 64)
  526. goto bad;
  527. case D_AX:
  528. case D_CX:
  529. case D_DX:
  530. case D_BX:
  531. case D_SP:
  532. case D_BP:
  533. case D_SI:
  534. case D_DI:
  535. i |= reg[base];
  536. break;
  537. }
  538. *andptr++ = i;
  539. return;
  540. bad:
  541. diag("asmidx: bad address %D", a);
  542. *andptr++ = 0;
  543. return;
  544. }
  545. static void
  546. put4(long v)
  547. {
  548. if(dlm && curp != P && reloca != nil){
  549. dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
  550. reloca = nil;
  551. }
  552. andptr[0] = v;
  553. andptr[1] = v>>8;
  554. andptr[2] = v>>16;
  555. andptr[3] = v>>24;
  556. andptr += 4;
  557. }
  558. static void
  559. put8(vlong v)
  560. {
  561. if(dlm && curp != P && reloca != nil){
  562. dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1); /* TO DO */
  563. reloca = nil;
  564. }
  565. andptr[0] = v;
  566. andptr[1] = v>>8;
  567. andptr[2] = v>>16;
  568. andptr[3] = v>>24;
  569. andptr[4] = v>>32;
  570. andptr[5] = v>>40;
  571. andptr[6] = v>>48;
  572. andptr[7] = v>>56;
  573. andptr += 8;
  574. }
  575. vlong
  576. vaddr(Adr *a)
  577. {
  578. int t;
  579. vlong v;
  580. Sym *s;
  581. t = a->type;
  582. v = a->offset;
  583. if(t == D_ADDR)
  584. t = a->index;
  585. switch(t) {
  586. case D_STATIC:
  587. case D_EXTERN:
  588. s = a->sym;
  589. if(s != nil) {
  590. if(dlm && curp != P)
  591. reloca = a;
  592. switch(s->type) {
  593. case SUNDEF:
  594. ckoff(s, v);
  595. case STEXT:
  596. case SCONST:
  597. if((uvlong)s->value < (uvlong)INITTEXT)
  598. v += INITTEXT; /* TO DO */
  599. v += s->value;
  600. break;
  601. default:
  602. v += INITDAT + s->value;
  603. }
  604. }
  605. }
  606. return v;
  607. }
  608. static void
  609. asmandsz(Adr *a, int r, int rex, int m64)
  610. {
  611. long v;
  612. int t;
  613. Adr aa;
  614. rex &= (0x40 | Rxr);
  615. v = a->offset;
  616. t = a->type;
  617. if(a->index != D_NONE) {
  618. if(t >= D_INDIR) {
  619. t -= D_INDIR;
  620. rexflag |= (regrex[a->index] & Rxx) | (regrex[t] & Rxb) | rex;
  621. if(t == D_NONE) {
  622. *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
  623. asmidx(a, t);
  624. put4(v);
  625. return;
  626. }
  627. if(v == 0 && t != D_BP && t != D_R13) {
  628. *andptr++ = (0 << 6) | (4 << 0) | (r << 3);
  629. asmidx(a, t);
  630. return;
  631. }
  632. if(v >= -128 && v < 128) {
  633. *andptr++ = (1 << 6) | (4 << 0) | (r << 3);
  634. asmidx(a, t);
  635. *andptr++ = v;
  636. return;
  637. }
  638. *andptr++ = (2 << 6) | (4 << 0) | (r << 3);
  639. asmidx(a, t);
  640. put4(v);
  641. return;
  642. }
  643. switch(t) {
  644. default:
  645. goto bad;
  646. case D_STATIC:
  647. case D_EXTERN:
  648. aa.type = D_NONE+D_INDIR;
  649. break;
  650. case D_AUTO:
  651. case D_PARAM:
  652. aa.type = D_SP+D_INDIR;
  653. break;
  654. }
  655. aa.offset = vaddr(a);
  656. aa.index = a->index;
  657. aa.scale = a->scale;
  658. asmandsz(&aa, r, rex, m64);
  659. return;
  660. }
  661. if(t >= D_AL && t <= D_X0+15) {
  662. if(v)
  663. goto bad;
  664. *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
  665. rexflag |= (regrex[t] & (0x40 | Rxb)) | rex;
  666. return;
  667. }
  668. if(t >= D_INDIR) {
  669. t -= D_INDIR;
  670. rexflag |= (regrex[t] & Rxb) | rex;
  671. if(t == D_NONE) {
  672. if(asmode != 64){
  673. *andptr++ = (0 << 6) | (5 << 0) | (r << 3);
  674. put4(v);
  675. return;
  676. }
  677. /* temporary */
  678. *andptr++ = (0 << 6) | (4 << 0) | (r << 3); /* sib present */
  679. *andptr++ = (0 << 6) | (4 << 3) | (5 << 0); /* DS:d32 */
  680. put4(v);
  681. return;
  682. }
  683. if(t == D_SP || t == D_R12) {
  684. if(v == 0) {
  685. *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
  686. asmidx(a, t);
  687. return;
  688. }
  689. if(v >= -128 && v < 128) {
  690. *andptr++ = (1 << 6) | (reg[t] << 0) | (r << 3);
  691. asmidx(a, t);
  692. *andptr++ = v;
  693. return;
  694. }
  695. *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
  696. asmidx(a, t);
  697. put4(v);
  698. return;
  699. }
  700. if(t >= D_AX && t <= D_R15) {
  701. if(v == 0 && t != D_BP && t != D_R13) {
  702. *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
  703. return;
  704. }
  705. if(v >= -128 && v < 128) {
  706. andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
  707. andptr[1] = v;
  708. andptr += 2;
  709. return;
  710. }
  711. *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
  712. put4(v);
  713. return;
  714. }
  715. goto bad;
  716. }
  717. switch(a->type) {
  718. default:
  719. goto bad;
  720. case D_STATIC:
  721. case D_EXTERN:
  722. aa.type = D_NONE+D_INDIR;
  723. break;
  724. case D_AUTO:
  725. case D_PARAM:
  726. aa.type = D_SP+D_INDIR;
  727. break;
  728. }
  729. aa.index = D_NONE;
  730. aa.scale = 1;
  731. aa.offset = vaddr(a);
  732. asmandsz(&aa, r, rex, m64);
  733. return;
  734. bad:
  735. diag("asmand: bad address %D", a);
  736. return;
  737. }
  738. void
  739. asmand(Adr *a, Adr *ra)
  740. {
  741. asmandsz(a, reg[ra->type], regrex[ra->type], 0);
  742. }
  743. void
  744. asmando(Adr *a, int o)
  745. {
  746. asmandsz(a, o, 0, 0);
  747. }
  748. static void
  749. bytereg(Adr *a)
  750. {
  751. if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15))
  752. a->type = D_AL + (a->type-D_AX);
  753. }
  754. #define E 0xff
  755. Movtab ymovtab[] =
  756. {
  757. /* push */
  758. {APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0},
  759. {APUSHL, Yss, Ynone, 0, 0x16,E,0,0},
  760. {APUSHL, Yds, Ynone, 0, 0x1e,E,0,0},
  761. {APUSHL, Yes, Ynone, 0, 0x06,E,0,0},
  762. {APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0},
  763. {APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0},
  764. {APUSHQ, Yfs, Ynone, 0, 0x0f,0xa0,E,0},
  765. {APUSHQ, Ygs, Ynone, 0, 0x0f,0xa8,E,0},
  766. {APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0},
  767. {APUSHW, Yss, Ynone, 0, Pe,0x16,E,0},
  768. {APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0},
  769. {APUSHW, Yes, Ynone, 0, Pe,0x06,E,0},
  770. {APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E},
  771. {APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E},
  772. /* pop */
  773. {APOPL, Ynone, Yds, 0, 0x1f,E,0,0},
  774. {APOPL, Ynone, Yes, 0, 0x07,E,0,0},
  775. {APOPL, Ynone, Yss, 0, 0x17,E,0,0},
  776. {APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0},
  777. {APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0},
  778. {APOPQ, Ynone, Yfs, 0, 0x0f,0xa1,E,0},
  779. {APOPQ, Ynone, Ygs, 0, 0x0f,0xa9,E,0},
  780. {APOPW, Ynone, Yds, 0, Pe,0x1f,E,0},
  781. {APOPW, Ynone, Yes, 0, Pe,0x07,E,0},
  782. {APOPW, Ynone, Yss, 0, Pe,0x17,E,0},
  783. {APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E},
  784. {APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E},
  785. /* mov seg */
  786. {AMOVW, Yes, Yml, 1, 0x8c,0,0,0},
  787. {AMOVW, Ycs, Yml, 1, 0x8c,1,0,0},
  788. {AMOVW, Yss, Yml, 1, 0x8c,2,0,0},
  789. {AMOVW, Yds, Yml, 1, 0x8c,3,0,0},
  790. {AMOVW, Yfs, Yml, 1, 0x8c,4,0,0},
  791. {AMOVW, Ygs, Yml, 1, 0x8c,5,0,0},
  792. {AMOVW, Yml, Yes, 2, 0x8e,0,0,0},
  793. {AMOVW, Yml, Ycs, 2, 0x8e,1,0,0},
  794. {AMOVW, Yml, Yss, 2, 0x8e,2,0,0},
  795. {AMOVW, Yml, Yds, 2, 0x8e,3,0,0},
  796. {AMOVW, Yml, Yfs, 2, 0x8e,4,0,0},
  797. {AMOVW, Yml, Ygs, 2, 0x8e,5,0,0},
  798. /* mov cr */
  799. {AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0},
  800. {AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0},
  801. {AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0},
  802. {AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0},
  803. {AMOVL, Ycr8, Yml, 3, 0x0f,0x20,8,0},
  804. {AMOVQ, Ycr0, Yml, 3, 0x0f,0x20,0,0},
  805. {AMOVQ, Ycr2, Yml, 3, 0x0f,0x20,2,0},
  806. {AMOVQ, Ycr3, Yml, 3, 0x0f,0x20,3,0},
  807. {AMOVQ, Ycr4, Yml, 3, 0x0f,0x20,4,0},
  808. {AMOVQ, Ycr8, Yml, 3, 0x0f,0x20,8,0},
  809. {AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0},
  810. {AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0},
  811. {AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0},
  812. {AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0},
  813. {AMOVL, Yml, Ycr8, 4, 0x0f,0x22,8,0},
  814. {AMOVQ, Yml, Ycr0, 4, 0x0f,0x22,0,0},
  815. {AMOVQ, Yml, Ycr2, 4, 0x0f,0x22,2,0},
  816. {AMOVQ, Yml, Ycr3, 4, 0x0f,0x22,3,0},
  817. {AMOVQ, Yml, Ycr4, 4, 0x0f,0x22,4,0},
  818. {AMOVQ, Yml, Ycr8, 4, 0x0f,0x22,8,0},
  819. /* mov dr */
  820. {AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0},
  821. {AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0},
  822. {AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0},
  823. {AMOVQ, Ydr0, Yml, 3, 0x0f,0x21,0,0},
  824. {AMOVQ, Ydr6, Yml, 3, 0x0f,0x21,6,0},
  825. {AMOVQ, Ydr7, Yml, 3, 0x0f,0x21,7,0},
  826. {AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0},
  827. {AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0},
  828. {AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0},
  829. {AMOVQ, Yml, Ydr0, 4, 0x0f,0x23,0,0},
  830. {AMOVQ, Yml, Ydr6, 4, 0x0f,0x23,6,0},
  831. {AMOVQ, Yml, Ydr7, 4, 0x0f,0x23,7,0},
  832. /* mov tr */
  833. {AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0},
  834. {AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0},
  835. {AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E},
  836. {AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E},
  837. /* lgdt, sgdt, lidt, sidt */
  838. {AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0},
  839. {AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0},
  840. {AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0},
  841. {AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0},
  842. {AMOVQ, Ym, Ygdtr, 4, 0x0f,0x01,2,0},
  843. {AMOVQ, Ygdtr, Ym, 3, 0x0f,0x01,0,0},
  844. {AMOVQ, Ym, Yidtr, 4, 0x0f,0x01,3,0},
  845. {AMOVQ, Yidtr, Ym, 3, 0x0f,0x01,1,0},
  846. /* lldt, sldt */
  847. {AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0},
  848. {AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0},
  849. /* lmsw, smsw */
  850. {AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0},
  851. {AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0},
  852. /* ltr, str */
  853. {AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0},
  854. {AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0},
  855. /* load full pointer */
  856. {AMOVL, Yml, Ycol, 5, 0,0,0,0},
  857. {AMOVW, Yml, Ycol, 5, Pe,0,0,0},
  858. /* double shift */
  859. {ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0},
  860. {ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0},
  861. {ASHLQ, Ycol, Yml, 6, Pw,0xa4,0xa5,0},
  862. {ASHRQ, Ycol, Yml, 6, Pw,0xac,0xad,0},
  863. {ASHLW, Ycol, Yml, 6, Pe,0xa4,0xa5,0},
  864. {ASHRW, Ycol, Yml, 6, Pe,0xac,0xad,0},
  865. 0
  866. };
  867. int
  868. isax(Adr *a)
  869. {
  870. switch(a->type) {
  871. case D_AX:
  872. case D_AL:
  873. case D_AH:
  874. case D_INDIR+D_AX:
  875. return 1;
  876. }
  877. if(a->index == D_AX)
  878. return 1;
  879. return 0;
  880. }
  881. void
  882. subreg(Prog *p, int from, int to)
  883. {
  884. if(debug['Q'])
  885. print("\n%P s/%R/%R/\n", p, from, to);
  886. if(p->from.type == from)
  887. p->from.type = to;
  888. if(p->to.type == from)
  889. p->to.type = to;
  890. if(p->from.index == from)
  891. p->from.index = to;
  892. if(p->to.index == from)
  893. p->to.index = to;
  894. from += D_INDIR;
  895. if(p->from.type == from)
  896. p->from.type = to+D_INDIR;
  897. if(p->to.type == from)
  898. p->to.type = to+D_INDIR;
  899. if(debug['Q'])
  900. print("%P\n", p);
  901. }
  902. static int
  903. mediaop(Optab *o, int op, int osize, int z)
  904. {
  905. switch(op){
  906. case Pm:
  907. case Pe:
  908. case Pf2:
  909. case Pf3:
  910. if(osize != 1){
  911. if(op != Pm)
  912. *andptr++ = op;
  913. *andptr++ = Pm;
  914. op = o->op[++z];
  915. break;
  916. }
  917. default:
  918. if(andptr == and || andptr[-1] != Pm)
  919. *andptr++ = Pm;
  920. break;
  921. }
  922. *andptr++ = op;
  923. return z;
  924. }
  925. void
  926. doasm(Prog *p)
  927. {
  928. Optab *o;
  929. Prog *q, pp;
  930. uchar *t;
  931. Movtab *mo;
  932. int z, op, ft, tt, xo, l;
  933. vlong v;
  934. o = opindex[p->as];
  935. if(o == nil) {
  936. diag("asmins: missing op %P", p);
  937. return;
  938. }
  939. ft = oclass(&p->from) * Ymax;
  940. tt = oclass(&p->to) * Ymax;
  941. t = o->ytab;
  942. if(t == 0) {
  943. diag("asmins: noproto %P", p);
  944. return;
  945. }
  946. xo = o->op[0] == 0x0f;
  947. for(z=0; *t; z+=t[3]+xo,t+=4)
  948. if(ycover[ft+t[0]])
  949. if(ycover[tt+t[1]])
  950. goto found;
  951. goto domov;
  952. found:
  953. switch(o->prefix) {
  954. case Pq: /* 16 bit escape and opcode escape */
  955. *andptr++ = Pe;
  956. *andptr++ = Pm;
  957. break;
  958. case Pf2: /* xmm opcode escape */
  959. case Pf3:
  960. *andptr++ = o->prefix;
  961. *andptr++ = Pm;
  962. break;
  963. case Pm: /* opcode escape */
  964. *andptr++ = Pm;
  965. break;
  966. case Pe: /* 16 bit escape */
  967. *andptr++ = Pe;
  968. break;
  969. case Pw: /* 64-bit escape */
  970. if(p->mode != 64)
  971. diag("asmins: illegal 64: %P", p);
  972. rexflag |= Pw;
  973. break;
  974. case Pb: /* botch */
  975. bytereg(&p->from);
  976. bytereg(&p->to);
  977. break;
  978. case P32: /* 32 bit but illegal if 64-bit mode */
  979. if(p->mode == 64)
  980. diag("asmins: illegal in 64-bit mode: %P", p);
  981. break;
  982. case Py: /* 64-bit only, no prefix */
  983. if(p->mode != 64)
  984. diag("asmins: illegal in %d-bit mode: %P", p->mode, p);
  985. break;
  986. }
  987. v = vaddr(&p->from);
  988. op = o->op[z];
  989. if(op == 0x0f) {
  990. *andptr++ = op;
  991. op = o->op[++z];
  992. }
  993. switch(t[2]) {
  994. default:
  995. diag("asmins: unknown z %d %P", t[2], p);
  996. return;
  997. case Zpseudo:
  998. break;
  999. case Zlit:
  1000. for(; op = o->op[z]; z++)
  1001. *andptr++ = op;
  1002. break;
  1003. case Zmb_r:
  1004. bytereg(&p->from);
  1005. /* fall through */
  1006. case Zm_r:
  1007. *andptr++ = op;
  1008. asmand(&p->from, &p->to);
  1009. break;
  1010. case Zm_r_xm:
  1011. mediaop(o, op, t[3], z);
  1012. asmand(&p->from, &p->to);
  1013. break;
  1014. case Zm_r_xm_nr:
  1015. rexflag = 0;
  1016. mediaop(o, op, t[3], z);
  1017. asmand(&p->from, &p->to);
  1018. break;
  1019. case Zm_r_i_xm:
  1020. mediaop(o, op, t[3], z);
  1021. asmand(&p->from, &p->to);
  1022. *andptr++ = p->to.offset;
  1023. break;
  1024. case Zm_r_3d:
  1025. *andptr++ = 0x0f;
  1026. *andptr++ = 0x0f;
  1027. asmand(&p->from, &p->to);
  1028. *andptr++ = op;
  1029. break;
  1030. case Zibm_r:
  1031. *andptr++ = op;
  1032. asmand(&p->from, &p->to);
  1033. *andptr++ = p->to.offset;
  1034. break;
  1035. case Zaut_r:
  1036. *andptr++ = 0x8d; /* leal */
  1037. if(p->from.type != D_ADDR)
  1038. diag("asmins: Zaut sb type ADDR");
  1039. p->from.type = p->from.index;
  1040. p->from.index = D_NONE;
  1041. asmand(&p->from, &p->to);
  1042. p->from.index = p->from.type;
  1043. p->from.type = D_ADDR;
  1044. break;
  1045. case Zm_o:
  1046. *andptr++ = op;
  1047. asmando(&p->from, o->op[z+1]);
  1048. break;
  1049. case Zr_m:
  1050. *andptr++ = op;
  1051. asmand(&p->to, &p->from);
  1052. break;
  1053. case Zr_m_xm:
  1054. mediaop(o, op, t[3], z);
  1055. asmand(&p->to, &p->from);
  1056. break;
  1057. case Zr_m_xm_nr:
  1058. rexflag = 0;
  1059. mediaop(o, op, t[3], z);
  1060. asmand(&p->to, &p->from);
  1061. break;
  1062. case Zr_m_i_xm:
  1063. mediaop(o, op, t[3], z);
  1064. asmand(&p->to, &p->from);
  1065. *andptr++ = p->from.offset;
  1066. break;
  1067. case Zo_m:
  1068. *andptr++ = op;
  1069. asmando(&p->to, o->op[z+1]);
  1070. break;
  1071. case Zo_m64:
  1072. *andptr++ = op;
  1073. asmandsz(&p->to, o->op[z+1], 0, 1);
  1074. break;
  1075. case Zm_ibo:
  1076. v = vaddr(&p->to);
  1077. *andptr++ = op;
  1078. asmando(&p->from, o->op[z+1]);
  1079. *andptr++ = v;
  1080. break;
  1081. case Zibo_m:
  1082. *andptr++ = op;
  1083. asmando(&p->to, o->op[z+1]);
  1084. *andptr++ = v;
  1085. break;
  1086. case Zibo_m_xm:
  1087. z = mediaop(o, op, t[3], z);
  1088. asmando(&p->to, o->op[z+1]);
  1089. *andptr++ = v;
  1090. break;
  1091. case Z_ib:
  1092. v = vaddr(&p->to);
  1093. case Zib_:
  1094. *andptr++ = op;
  1095. *andptr++ = v;
  1096. break;
  1097. case Zib_rp:
  1098. rexflag |= regrex[p->to.type] & (Rxb|0x40);
  1099. *andptr++ = op + reg[p->to.type];
  1100. *andptr++ = v;
  1101. break;
  1102. case Zil_rp:
  1103. rexflag |= regrex[p->to.type] & Rxb;
  1104. *andptr++ = op + reg[p->to.type];
  1105. if(o->prefix == Pe) {
  1106. *andptr++ = v;
  1107. *andptr++ = v>>8;
  1108. }
  1109. else
  1110. put4(v);
  1111. break;
  1112. case Zo_iw:
  1113. *andptr++ = op;
  1114. if(p->from.type != D_NONE){
  1115. *andptr++ = v;
  1116. *andptr++ = v>>8;
  1117. }
  1118. break;
  1119. case Ziq_rp:
  1120. l = v>>32;
  1121. if(l == 0){
  1122. //p->mark |= 0100;
  1123. //print("zero: %llux %P\n", v, p);
  1124. rexflag &= ~(0x40|Rxw);
  1125. rexflag |= regrex[p->to.type] & Rxb;
  1126. *andptr++ = 0xb8 + reg[p->to.type];
  1127. put4(v);
  1128. }else if(l == -1 && (v&((uvlong)1<<31))!=0){ /* sign extend */
  1129. //p->mark |= 0100;
  1130. //print("sign: %llux %P\n", v, p);
  1131. *andptr ++ = 0xc7;
  1132. asmando(&p->to, 0);
  1133. put4(v);
  1134. }else{ /* need all 8 */
  1135. //print("all: %llux %P\n", v, p);
  1136. rexflag |= regrex[p->to.type] & Rxb;
  1137. *andptr++ = op + reg[p->to.type];
  1138. put8(v);
  1139. }
  1140. break;
  1141. case Zib_rr:
  1142. *andptr++ = op;
  1143. asmand(&p->to, &p->to);
  1144. *andptr++ = v;
  1145. break;
  1146. case Z_il:
  1147. v = vaddr(&p->to);
  1148. case Zil_:
  1149. *andptr++ = op;
  1150. if(o->prefix == Pe) {
  1151. *andptr++ = v;
  1152. *andptr++ = v>>8;
  1153. }
  1154. else
  1155. put4(v);
  1156. break;
  1157. case Zm_ilo:
  1158. v = vaddr(&p->to);
  1159. *andptr++ = op;
  1160. asmando(&p->from, o->op[z+1]);
  1161. if(o->prefix == Pe) {
  1162. *andptr++ = v;
  1163. *andptr++ = v>>8;
  1164. }
  1165. else
  1166. put4(v);
  1167. break;
  1168. case Zilo_m:
  1169. *andptr++ = op;
  1170. asmando(&p->to, o->op[z+1]);
  1171. if(o->prefix == Pe) {
  1172. *andptr++ = v;
  1173. *andptr++ = v>>8;
  1174. }
  1175. else
  1176. put4(v);
  1177. break;
  1178. case Zil_rr:
  1179. *andptr++ = op;
  1180. asmand(&p->to, &p->to);
  1181. if(o->prefix == Pe) {
  1182. *andptr++ = v;
  1183. *andptr++ = v>>8;
  1184. }
  1185. else
  1186. put4(v);
  1187. break;
  1188. case Z_rp:
  1189. rexflag |= regrex[p->to.type] & (Rxb|0x40);
  1190. *andptr++ = op + reg[p->to.type];
  1191. break;
  1192. case Zrp_:
  1193. rexflag |= regrex[p->from.type] & (Rxb|0x40);
  1194. *andptr++ = op + reg[p->from.type];
  1195. break;
  1196. case Zclr:
  1197. *andptr++ = op;
  1198. asmand(&p->to, &p->to);
  1199. break;
  1200. case Zbr:
  1201. q = p->pcond;
  1202. if(q) {
  1203. v = q->pc - p->pc - 2;
  1204. if(v >= -128 && v <= 127) {
  1205. *andptr++ = op;
  1206. *andptr++ = v;
  1207. } else {
  1208. v -= 6-2;
  1209. *andptr++ = 0x0f;
  1210. *andptr++ = o->op[z+1];
  1211. *andptr++ = v;
  1212. *andptr++ = v>>8;
  1213. *andptr++ = v>>16;
  1214. *andptr++ = v>>24;
  1215. }
  1216. }
  1217. break;
  1218. case Zcall:
  1219. q = p->pcond;
  1220. if(q) {
  1221. v = q->pc - p->pc - 5;
  1222. if(dlm && curp != P && p->to.sym->type == SUNDEF){
  1223. /* v = 0 - p->pc - 5; */
  1224. v = 0;
  1225. ckoff(p->to.sym, v);
  1226. v += p->to.sym->value;
  1227. dynreloc(p->to.sym, p->pc+1, 0);
  1228. }
  1229. *andptr++ = op;
  1230. *andptr++ = v;
  1231. *andptr++ = v>>8;
  1232. *andptr++ = v>>16;
  1233. *andptr++ = v>>24;
  1234. }
  1235. break;
  1236. case Zjmp:
  1237. q = p->pcond;
  1238. if(q) {
  1239. v = q->pc - p->pc - 2;
  1240. if(v >= -128 && v <= 127) {
  1241. *andptr++ = op;
  1242. *andptr++ = v;
  1243. } else {
  1244. v -= 5-2;
  1245. *andptr++ = o->op[z+1];
  1246. *andptr++ = v;
  1247. *andptr++ = v>>8;
  1248. *andptr++ = v>>16;
  1249. *andptr++ = v>>24;
  1250. }
  1251. }
  1252. break;
  1253. case Zloop:
  1254. q = p->pcond;
  1255. if(q) {
  1256. v = q->pc - p->pc - 2;
  1257. if(v < -128 && v > 127)
  1258. diag("loop too far: %P", p);
  1259. *andptr++ = op;
  1260. *andptr++ = v;
  1261. }
  1262. break;
  1263. case Zbyte:
  1264. *andptr++ = v;
  1265. if(op > 1) {
  1266. *andptr++ = v>>8;
  1267. if(op > 2) {
  1268. *andptr++ = v>>16;
  1269. *andptr++ = v>>24;
  1270. if(op > 4) {
  1271. *andptr++ = v>>32;
  1272. *andptr++ = v>>40;
  1273. *andptr++ = v>>48;
  1274. *andptr++ = v>>56;
  1275. }
  1276. }
  1277. }
  1278. break;
  1279. }
  1280. return;
  1281. domov:
  1282. for(mo=ymovtab; mo->as; mo++)
  1283. if(p->as == mo->as)
  1284. if(ycover[ft+mo->ft])
  1285. if(ycover[tt+mo->tt]){
  1286. t = mo->op;
  1287. goto mfound;
  1288. }
  1289. bad:
  1290. if(p->mode != 64){
  1291. /*
  1292. * here, the assembly has failed.
  1293. * if its a byte instruction that has
  1294. * unaddressable registers, try to
  1295. * exchange registers and reissue the
  1296. * instruction with the operands renamed.
  1297. */
  1298. pp = *p;
  1299. z = p->from.type;
  1300. if(z >= D_BP && z <= D_DI) {
  1301. if(isax(&p->to)) {
  1302. *andptr++ = 0x87; /* xchg lhs,bx */
  1303. asmando(&p->from, reg[D_BX]);
  1304. subreg(&pp, z, D_BX);
  1305. doasm(&pp);
  1306. *andptr++ = 0x87; /* xchg lhs,bx */
  1307. asmando(&p->from, reg[D_BX]);
  1308. } else {
  1309. *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
  1310. subreg(&pp, z, D_AX);
  1311. doasm(&pp);
  1312. *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */
  1313. }
  1314. return;
  1315. }
  1316. z = p->to.type;
  1317. if(z >= D_BP && z <= D_DI) {
  1318. if(isax(&p->from)) {
  1319. *andptr++ = 0x87; /* xchg rhs,bx */
  1320. asmando(&p->to, reg[D_BX]);
  1321. subreg(&pp, z, D_BX);
  1322. doasm(&pp);
  1323. *andptr++ = 0x87; /* xchg rhs,bx */
  1324. asmando(&p->to, reg[D_BX]);
  1325. } else {
  1326. *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
  1327. subreg(&pp, z, D_AX);
  1328. doasm(&pp);
  1329. *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */
  1330. }
  1331. return;
  1332. }
  1333. }
  1334. diag("doasm: notfound from=%ux to=%ux %P", p->from.type, p->to.type, p);
  1335. return;
  1336. mfound:
  1337. switch(mo->code) {
  1338. default:
  1339. diag("asmins: unknown mov %d %P", mo->code, p);
  1340. break;
  1341. case 0: /* lit */
  1342. for(z=0; t[z]!=E; z++)
  1343. *andptr++ = t[z];
  1344. break;
  1345. case 1: /* r,m */
  1346. *andptr++ = t[0];
  1347. asmando(&p->to, t[1]);
  1348. break;
  1349. case 2: /* m,r */
  1350. *andptr++ = t[0];
  1351. asmando(&p->from, t[1]);
  1352. break;
  1353. case 3: /* r,m - 2op */
  1354. *andptr++ = t[0];
  1355. *andptr++ = t[1];
  1356. asmando(&p->to, t[2]);
  1357. rexflag |= regrex[p->from.type] & (Rxr|0x40);
  1358. break;
  1359. case 4: /* m,r - 2op */
  1360. *andptr++ = t[0];
  1361. *andptr++ = t[1];
  1362. asmando(&p->from, t[2]);
  1363. rexflag |= regrex[p->to.type] & (Rxr|0x40);
  1364. break;
  1365. case 5: /* load full pointer, trash heap */
  1366. if(t[0])
  1367. *andptr++ = t[0];
  1368. switch(p->to.index) {
  1369. default:
  1370. goto bad;
  1371. case D_DS:
  1372. *andptr++ = 0xc5;
  1373. break;
  1374. case D_SS:
  1375. *andptr++ = 0x0f;
  1376. *andptr++ = 0xb2;
  1377. break;
  1378. case D_ES:
  1379. *andptr++ = 0xc4;
  1380. break;
  1381. case D_FS:
  1382. *andptr++ = 0x0f;
  1383. *andptr++ = 0xb4;
  1384. break;
  1385. case D_GS:
  1386. *andptr++ = 0x0f;
  1387. *andptr++ = 0xb5;
  1388. break;
  1389. }
  1390. asmand(&p->from, &p->to);
  1391. break;
  1392. case 6: /* double shift */
  1393. if(t[0] == Pw){
  1394. if(p->mode != 64)
  1395. diag("asmins: illegal 64: %P", p);
  1396. rexflag |= Pw;
  1397. t++;
  1398. }else if(t[0] == Pe){
  1399. *andptr++ = Pe;
  1400. t++;
  1401. }
  1402. z = p->from.type;
  1403. switch(z) {
  1404. default:
  1405. goto bad;
  1406. case D_CONST:
  1407. *andptr++ = 0x0f;
  1408. *andptr++ = t[0];
  1409. asmandsz(&p->to, reg[p->from.index], regrex[p->from.index], 0);
  1410. *andptr++ = p->from.offset;
  1411. break;
  1412. case D_CL:
  1413. case D_CX:
  1414. *andptr++ = 0x0f;
  1415. *andptr++ = t[1];
  1416. asmandsz(&p->to, reg[p->from.index], regrex[p->from.index], 0);
  1417. break;
  1418. }
  1419. break;
  1420. }
  1421. }
  1422. void
  1423. asmins(Prog *p)
  1424. {
  1425. int n, np, c;
  1426. rexflag = 0;
  1427. andptr = and;
  1428. asmode = p->mode;
  1429. doasm(p);
  1430. if(rexflag){
  1431. /*
  1432. * as befits the whole approach of the architecture,
  1433. * the rex prefix must appear before the first opcode byte
  1434. * (and thus after any 66/67/f2/f3 prefix bytes, but
  1435. * before the 0f opcode escape!), or it might be ignored.
  1436. * note that the handbook often misleadingly shows 66/f2/f3 in `opcode'.
  1437. */
  1438. if(p->mode != 64)
  1439. diag("asmins: illegal in mode %d: %P", p->mode, p);
  1440. n = andptr - and;
  1441. for(np = 0; np < n; np++) {
  1442. c = and[np];
  1443. if(c != 0x66 && c != 0xf2 && c != 0xf3 && c != 0x67)
  1444. break;
  1445. }
  1446. memmove(and+np+1, and+np, n-np);
  1447. and[np] = 0x40 | rexflag;
  1448. andptr++;
  1449. }
  1450. }
  1451. enum{
  1452. ABSD = 0,
  1453. ABSU = 1,
  1454. RELD = 2,
  1455. RELU = 3,
  1456. };
  1457. int modemap[4] = { 0, 1, -1, 2, };
  1458. typedef struct Reloc Reloc;
  1459. struct Reloc
  1460. {
  1461. int n;
  1462. int t;
  1463. uchar *m;
  1464. ulong *a;
  1465. };
  1466. Reloc rels;
  1467. static void
  1468. grow(Reloc *r)
  1469. {
  1470. int t;
  1471. uchar *m, *nm;
  1472. ulong *a, *na;
  1473. t = r->t;
  1474. r->t += 64;
  1475. m = r->m;
  1476. a = r->a;
  1477. r->m = nm = malloc(r->t*sizeof(uchar));
  1478. r->a = na = malloc(r->t*sizeof(ulong));
  1479. memmove(nm, m, t*sizeof(uchar));
  1480. memmove(na, a, t*sizeof(ulong));
  1481. free(m);
  1482. free(a);
  1483. }
  1484. void
  1485. dynreloc(Sym *s, ulong v, int abs)
  1486. {
  1487. int i, k, n;
  1488. uchar *m;
  1489. ulong *a;
  1490. Reloc *r;
  1491. if(s->type == SUNDEF)
  1492. k = abs ? ABSU : RELU;
  1493. else
  1494. k = abs ? ABSD : RELD;
  1495. /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
  1496. k = modemap[k];
  1497. r = &rels;
  1498. n = r->n;
  1499. if(n >= r->t)
  1500. grow(r);
  1501. m = r->m;
  1502. a = r->a;
  1503. for(i = n; i > 0; i--){
  1504. if(v < a[i-1]){ /* happens occasionally for data */
  1505. m[i] = m[i-1];
  1506. a[i] = a[i-1];
  1507. }
  1508. else
  1509. break;
  1510. }
  1511. m[i] = k;
  1512. a[i] = v;
  1513. r->n++;
  1514. }
  1515. static int
  1516. sput(char *s)
  1517. {
  1518. char *p;
  1519. p = s;
  1520. while(*s)
  1521. cput(*s++);
  1522. cput(0);
  1523. return s-p+1;
  1524. }
  1525. void
  1526. asmdyn()
  1527. {
  1528. int i, n, t, c;
  1529. Sym *s;
  1530. ulong la, ra, *a;
  1531. vlong off;
  1532. uchar *m;
  1533. Reloc *r;
  1534. cflush();
  1535. off = seek(cout, 0, 1);
  1536. lput(0);
  1537. t = 0;
  1538. lput(imports);
  1539. t += 4;
  1540. for(i = 0; i < NHASH; i++)
  1541. for(s = hash[i]; s != S; s = s->link)
  1542. if(s->type == SUNDEF){
  1543. lput(s->sig);
  1544. t += 4;
  1545. t += sput(s->name);
  1546. }
  1547. la = 0;
  1548. r = &rels;
  1549. n = r->n;
  1550. m = r->m;
  1551. a = r->a;
  1552. lput(n);
  1553. t += 4;
  1554. for(i = 0; i < n; i++){
  1555. ra = *a-la;
  1556. if(*a < la)
  1557. diag("bad relocation order");
  1558. if(ra < 256)
  1559. c = 0;
  1560. else if(ra < 65536)
  1561. c = 1;
  1562. else
  1563. c = 2;
  1564. cput((c<<6)|*m++);
  1565. t++;
  1566. if(c == 0){
  1567. cput(ra);
  1568. t++;
  1569. }
  1570. else if(c == 1){
  1571. wput(ra);
  1572. t += 2;
  1573. }
  1574. else{
  1575. lput(ra);
  1576. t += 4;
  1577. }
  1578. la = *a++;
  1579. }
  1580. cflush();
  1581. seek(cout, off, 0);
  1582. lput(t);
  1583. if(debug['v']){
  1584. Bprint(&bso, "import table entries = %d\n", imports);
  1585. Bprint(&bso, "export table entries = %d\n", exports);
  1586. }
  1587. }