sysv.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. #include "all.h"
  2. typedef struct AClass AClass;
  3. typedef struct RAlloc RAlloc;
  4. struct AClass {
  5. Typ *type;
  6. int inmem;
  7. int align;
  8. uint size;
  9. int cls[2];
  10. Ref ref[2];
  11. };
  12. struct RAlloc {
  13. Ins i;
  14. RAlloc *link;
  15. };
  16. static void
  17. classify(AClass *a, Typ *t, uint s)
  18. {
  19. Field *f;
  20. int *cls;
  21. uint n, s1;
  22. for (n=0, s1=s; n<t->nunion; n++, s=s1)
  23. for (f=t->fields[n]; f->type!=FEnd; f++) {
  24. assert(s <= 16);
  25. cls = &a->cls[s/8];
  26. switch (f->type) {
  27. case FEnd:
  28. die("unreachable");
  29. case FPad:
  30. /* don't change anything */
  31. s += f->len;
  32. break;
  33. case Fs:
  34. case Fd:
  35. if (*cls == Kx)
  36. *cls = Kd;
  37. s += f->len;
  38. break;
  39. case Fb:
  40. case Fh:
  41. case Fw:
  42. case Fl:
  43. *cls = Kl;
  44. s += f->len;
  45. break;
  46. case FTyp:
  47. classify(a, &typ[f->len], s);
  48. s += typ[f->len].size;
  49. break;
  50. }
  51. }
  52. }
  53. static void
  54. typclass(AClass *a, Typ *t)
  55. {
  56. uint sz, al;
  57. sz = t->size;
  58. al = 1u << t->align;
  59. /* the ABI requires sizes to be rounded
  60. * up to the nearest multiple of 8, moreover
  61. * it makes it easy load and store structures
  62. * in registers
  63. */
  64. if (al < 8)
  65. al = 8;
  66. sz = (sz + al-1) & -al;
  67. a->type = t;
  68. a->size = sz;
  69. a->align = t->align;
  70. if (t->isdark || sz > 16 || sz == 0) {
  71. /* large or unaligned structures are
  72. * required to be passed in memory
  73. */
  74. a->inmem = 1;
  75. return;
  76. }
  77. a->cls[0] = Kx;
  78. a->cls[1] = Kx;
  79. a->inmem = 0;
  80. classify(a, t, 0);
  81. }
  82. static int
  83. retr(Ref reg[2], AClass *aret)
  84. {
  85. static int retreg[2][2] = {{RAX, RDX}, {XMM0, XMM0+1}};
  86. int n, k, ca, nr[2];
  87. nr[0] = nr[1] = 0;
  88. ca = 0;
  89. for (n=0; (uint)n*8<aret->size; n++) {
  90. k = KBASE(aret->cls[n]);
  91. reg[n] = TMP(retreg[k][nr[k]++]);
  92. ca += 1 << (2 * k);
  93. }
  94. return ca;
  95. }
  96. static void
  97. selret(Blk *b, Fn *fn)
  98. {
  99. int j, k, ca;
  100. Ref r, r0, reg[2];
  101. AClass aret;
  102. j = b->jmp.type;
  103. if (!isret(j) || j == Jret0)
  104. return;
  105. r0 = b->jmp.arg;
  106. b->jmp.type = Jret0;
  107. if (j == Jretc) {
  108. typclass(&aret, &typ[fn->retty]);
  109. if (aret.inmem) {
  110. assert(rtype(fn->retr) == RTmp);
  111. emit(Ocopy, Kl, TMP(RAX), fn->retr, R);
  112. emit(Oblit1, 0, R, INT(aret.type->size), R);
  113. emit(Oblit0, 0, R, r0, fn->retr);
  114. ca = 1;
  115. } else {
  116. ca = retr(reg, &aret);
  117. if (aret.size > 8) {
  118. r = newtmp("abi", Kl, fn);
  119. emit(Oload, Kl, reg[1], r, R);
  120. emit(Oadd, Kl, r, r0, getcon(8, fn));
  121. }
  122. emit(Oload, Kl, reg[0], r0, R);
  123. }
  124. } else {
  125. k = j - Jretw;
  126. if (KBASE(k) == 0) {
  127. emit(Ocopy, k, TMP(RAX), r0, R);
  128. ca = 1;
  129. } else {
  130. emit(Ocopy, k, TMP(XMM0), r0, R);
  131. ca = 1 << 2;
  132. }
  133. }
  134. b->jmp.arg = CALL(ca);
  135. }
  136. static int
  137. argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env)
  138. {
  139. int varc, envc, nint, ni, nsse, ns, n, *pn;
  140. AClass *a;
  141. Ins *i;
  142. if (aret && aret->inmem)
  143. nint = 5; /* hidden argument */
  144. else
  145. nint = 6;
  146. nsse = 8;
  147. varc = 0;
  148. envc = 0;
  149. for (i=i0, a=ac; i<i1; i++, a++)
  150. switch (i->op - op + Oarg) {
  151. case Oarg:
  152. if (KBASE(i->cls) == 0)
  153. pn = &nint;
  154. else
  155. pn = &nsse;
  156. if (*pn > 0) {
  157. --*pn;
  158. a->inmem = 0;
  159. } else
  160. a->inmem = 2;
  161. a->align = 3;
  162. a->size = 8;
  163. a->cls[0] = i->cls;
  164. break;
  165. case Oargc:
  166. n = i->arg[0].val;
  167. typclass(a, &typ[n]);
  168. if (a->inmem)
  169. continue;
  170. ni = ns = 0;
  171. for (n=0; (uint)n*8<a->size; n++)
  172. if (KBASE(a->cls[n]) == 0)
  173. ni++;
  174. else
  175. ns++;
  176. if (nint >= ni && nsse >= ns) {
  177. nint -= ni;
  178. nsse -= ns;
  179. } else
  180. a->inmem = 1;
  181. break;
  182. case Oarge:
  183. envc = 1;
  184. if (op == Opar)
  185. *env = i->to;
  186. else
  187. *env = i->arg[0];
  188. break;
  189. case Oargv:
  190. varc = 1;
  191. break;
  192. default:
  193. die("unreachable");
  194. }
  195. if (varc && envc)
  196. err("sysv abi does not support variadic env calls");
  197. return ((varc|envc) << 12) | ((6-nint) << 4) | ((8-nsse) << 8);
  198. }
  199. int amd64_sysv_rsave[] = {
  200. RDI, RSI, RDX, RCX, R8, R9, R10, R11, RAX,
  201. XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
  202. XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, -1
  203. };
  204. int amd64_sysv_rclob[] = {RBX, R12, R13, R14, R15, -1};
  205. MAKESURE(sysv_arrays_ok,
  206. sizeof amd64_sysv_rsave == (NGPS+NFPS+1) * sizeof(int) &&
  207. sizeof amd64_sysv_rclob == (NCLR+1) * sizeof(int)
  208. );
  209. /* layout of call's second argument (RCall)
  210. *
  211. * 29 12 8 4 3 0
  212. * |0...00|x|xxxx|xxxx|xx|xx| range
  213. * | | | | ` gp regs returned (0..2)
  214. * | | | ` sse regs returned (0..2)
  215. * | | ` gp regs passed (0..6)
  216. * | ` sse regs passed (0..8)
  217. * ` 1 if rax is used to pass data (0..1)
  218. */
  219. bits
  220. amd64_sysv_retregs(Ref r, int p[2])
  221. {
  222. bits b;
  223. int ni, nf;
  224. assert(rtype(r) == RCall);
  225. b = 0;
  226. ni = r.val & 3;
  227. nf = (r.val >> 2) & 3;
  228. if (ni >= 1)
  229. b |= BIT(RAX);
  230. if (ni >= 2)
  231. b |= BIT(RDX);
  232. if (nf >= 1)
  233. b |= BIT(XMM0);
  234. if (nf >= 2)
  235. b |= BIT(XMM1);
  236. if (p) {
  237. p[0] = ni;
  238. p[1] = nf;
  239. }
  240. return b;
  241. }
  242. bits
  243. amd64_sysv_argregs(Ref r, int p[2])
  244. {
  245. bits b;
  246. int j, ni, nf, ra;
  247. assert(rtype(r) == RCall);
  248. b = 0;
  249. ni = (r.val >> 4) & 15;
  250. nf = (r.val >> 8) & 15;
  251. ra = (r.val >> 12) & 1;
  252. for (j=0; j<ni; j++)
  253. b |= BIT(amd64_sysv_rsave[j]);
  254. for (j=0; j<nf; j++)
  255. b |= BIT(XMM0+j);
  256. if (p) {
  257. p[0] = ni + ra;
  258. p[1] = nf;
  259. }
  260. return b | (ra ? BIT(RAX) : 0);
  261. }
  262. static Ref
  263. rarg(int ty, int *ni, int *ns)
  264. {
  265. if (KBASE(ty) == 0)
  266. return TMP(amd64_sysv_rsave[(*ni)++]);
  267. else
  268. return TMP(XMM0 + (*ns)++);
  269. }
  270. static void
  271. selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
  272. {
  273. Ins *i;
  274. AClass *ac, *a, aret;
  275. int ca, ni, ns, al;
  276. uint stk, off;
  277. Ref r, r1, r2, reg[2], env;
  278. RAlloc *ra;
  279. env = R;
  280. ac = alloc((i1-i0) * sizeof ac[0]);
  281. if (!req(i1->arg[1], R)) {
  282. assert(rtype(i1->arg[1]) == RType);
  283. typclass(&aret, &typ[i1->arg[1].val]);
  284. ca = argsclass(i0, i1, ac, Oarg, &aret, &env);
  285. } else
  286. ca = argsclass(i0, i1, ac, Oarg, 0, &env);
  287. for (stk=0, a=&ac[i1-i0]; a>ac;)
  288. if ((--a)->inmem) {
  289. if (a->align > 4)
  290. err("sysv abi requires alignments of 16 or less");
  291. stk += a->size;
  292. if (a->align == 4)
  293. stk += stk & 15;
  294. }
  295. stk += stk & 15;
  296. if (stk) {
  297. r = getcon(-(int64_t)stk, fn);
  298. emit(Osalloc, Kl, R, r, R);
  299. }
  300. if (!req(i1->arg[1], R)) {
  301. if (aret.inmem) {
  302. /* get the return location from eax
  303. * it saves one callee-save reg */
  304. r1 = newtmp("abi", Kl, fn);
  305. emit(Ocopy, Kl, i1->to, TMP(RAX), R);
  306. ca += 1;
  307. } else {
  308. /* todo, may read out of bounds.
  309. * gcc did this up until 5.2, but
  310. * this should still be fixed.
  311. */
  312. if (aret.size > 8) {
  313. r = newtmp("abi", Kl, fn);
  314. aret.ref[1] = newtmp("abi", aret.cls[1], fn);
  315. emit(Ostorel, 0, R, aret.ref[1], r);
  316. emit(Oadd, Kl, r, i1->to, getcon(8, fn));
  317. }
  318. aret.ref[0] = newtmp("abi", aret.cls[0], fn);
  319. emit(Ostorel, 0, R, aret.ref[0], i1->to);
  320. ca += retr(reg, &aret);
  321. if (aret.size > 8)
  322. emit(Ocopy, aret.cls[1], aret.ref[1], reg[1], R);
  323. emit(Ocopy, aret.cls[0], aret.ref[0], reg[0], R);
  324. r1 = i1->to;
  325. }
  326. /* allocate return pad */
  327. ra = alloc(sizeof *ra);
  328. /* specific to NAlign == 3 */
  329. al = aret.align >= 2 ? aret.align - 2 : 0;
  330. ra->i = (Ins){Oalloc+al, Kl, r1, {getcon(aret.size, fn)}};
  331. ra->link = (*rap);
  332. *rap = ra;
  333. } else {
  334. ra = 0;
  335. if (KBASE(i1->cls) == 0) {
  336. emit(Ocopy, i1->cls, i1->to, TMP(RAX), R);
  337. ca += 1;
  338. } else {
  339. emit(Ocopy, i1->cls, i1->to, TMP(XMM0), R);
  340. ca += 1 << 2;
  341. }
  342. }
  343. emit(Ocall, i1->cls, R, i1->arg[0], CALL(ca));
  344. if (!req(R, env))
  345. emit(Ocopy, Kl, TMP(RAX), env, R);
  346. else if ((ca >> 12) & 1) /* vararg call */
  347. emit(Ocopy, Kw, TMP(RAX), getcon((ca >> 8) & 15, fn), R);
  348. ni = ns = 0;
  349. if (ra && aret.inmem)
  350. emit(Ocopy, Kl, rarg(Kl, &ni, &ns), ra->i.to, R); /* pass hidden argument */
  351. for (i=i0, a=ac; i<i1; i++, a++) {
  352. if (i->op >= Oarge || a->inmem)
  353. continue;
  354. r1 = rarg(a->cls[0], &ni, &ns);
  355. if (i->op == Oargc) {
  356. if (a->size > 8) {
  357. r2 = rarg(a->cls[1], &ni, &ns);
  358. r = newtmp("abi", Kl, fn);
  359. emit(Oload, a->cls[1], r2, r, R);
  360. emit(Oadd, Kl, r, i->arg[1], getcon(8, fn));
  361. }
  362. emit(Oload, a->cls[0], r1, i->arg[1], R);
  363. } else
  364. emit(Ocopy, i->cls, r1, i->arg[0], R);
  365. }
  366. if (!stk)
  367. return;
  368. r = newtmp("abi", Kl, fn);
  369. for (i=i0, a=ac, off=0; i<i1; i++, a++) {
  370. if (i->op >= Oarge || !a->inmem)
  371. continue;
  372. r1 = newtmp("abi", Kl, fn);
  373. if (i->op == Oargc) {
  374. if (a->align == 4)
  375. off += off & 15;
  376. emit(Oblit1, 0, R, INT(a->type->size), R);
  377. emit(Oblit0, 0, R, i->arg[1], r1);
  378. } else
  379. emit(Ostorel, 0, R, i->arg[0], r1);
  380. emit(Oadd, Kl, r1, r, getcon(off, fn));
  381. off += a->size;
  382. }
  383. emit(Osalloc, Kl, r, getcon(stk, fn), R);
  384. }
  385. static int
  386. selpar(Fn *fn, Ins *i0, Ins *i1)
  387. {
  388. AClass *ac, *a, aret;
  389. Ins *i;
  390. int ni, ns, s, al, fa;
  391. Ref r, env;
  392. env = R;
  393. ac = alloc((i1-i0) * sizeof ac[0]);
  394. curi = &insb[NIns];
  395. ni = ns = 0;
  396. if (fn->retty >= 0) {
  397. typclass(&aret, &typ[fn->retty]);
  398. fa = argsclass(i0, i1, ac, Opar, &aret, &env);
  399. } else
  400. fa = argsclass(i0, i1, ac, Opar, 0, &env);
  401. fn->reg = amd64_sysv_argregs(CALL(fa), 0);
  402. for (i=i0, a=ac; i<i1; i++, a++) {
  403. if (i->op != Oparc || a->inmem)
  404. continue;
  405. if (a->size > 8) {
  406. r = newtmp("abi", Kl, fn);
  407. a->ref[1] = newtmp("abi", Kl, fn);
  408. emit(Ostorel, 0, R, a->ref[1], r);
  409. emit(Oadd, Kl, r, i->to, getcon(8, fn));
  410. }
  411. a->ref[0] = newtmp("abi", Kl, fn);
  412. emit(Ostorel, 0, R, a->ref[0], i->to);
  413. /* specific to NAlign == 3 */
  414. al = a->align >= 2 ? a->align - 2 : 0;
  415. emit(Oalloc+al, Kl, i->to, getcon(a->size, fn), R);
  416. }
  417. if (fn->retty >= 0 && aret.inmem) {
  418. r = newtmp("abi", Kl, fn);
  419. emit(Ocopy, Kl, r, rarg(Kl, &ni, &ns), R);
  420. fn->retr = r;
  421. }
  422. for (i=i0, a=ac, s=4; i<i1; i++, a++) {
  423. switch (a->inmem) {
  424. case 1:
  425. if (a->align > 4)
  426. err("sysv abi requires alignments of 16 or less");
  427. if (a->align == 4)
  428. s = (s+3) & -4;
  429. fn->tmp[i->to.val].slot = -s;
  430. s += a->size / 4;
  431. continue;
  432. case 2:
  433. emit(Oload, i->cls, i->to, SLOT(-s), R);
  434. s += 2;
  435. continue;
  436. }
  437. if (i->op == Opare)
  438. continue;
  439. r = rarg(a->cls[0], &ni, &ns);
  440. if (i->op == Oparc) {
  441. emit(Ocopy, a->cls[0], a->ref[0], r, R);
  442. if (a->size > 8) {
  443. r = rarg(a->cls[1], &ni, &ns);
  444. emit(Ocopy, a->cls[1], a->ref[1], r, R);
  445. }
  446. } else
  447. emit(Ocopy, i->cls, i->to, r, R);
  448. }
  449. if (!req(R, env))
  450. emit(Ocopy, Kl, env, TMP(RAX), R);
  451. return fa | (s*4)<<12;
  452. }
  453. static Blk *
  454. split(Fn *fn, Blk *b)
  455. {
  456. Blk *bn;
  457. ++fn->nblk;
  458. bn = newblk();
  459. bn->nins = &insb[NIns] - curi;
  460. idup(&bn->ins, curi, bn->nins);
  461. curi = &insb[NIns];
  462. bn->visit = ++b->visit;
  463. strf(bn->name, "%s.%d", b->name, b->visit);
  464. bn->loop = b->loop;
  465. bn->link = b->link;
  466. b->link = bn;
  467. return bn;
  468. }
  469. static void
  470. chpred(Blk *b, Blk *bp, Blk *bp1)
  471. {
  472. Phi *p;
  473. uint a;
  474. for (p=b->phi; p; p=p->link) {
  475. for (a=0; p->blk[a]!=bp; a++)
  476. assert(a+1<p->narg);
  477. p->blk[a] = bp1;
  478. }
  479. }
  480. static void
  481. selvaarg(Fn *fn, Blk *b, Ins *i)
  482. {
  483. Ref loc, lreg, lstk, nr, r0, r1, c4, c8, c16, c, ap;
  484. Blk *b0, *bstk, *breg;
  485. int isint;
  486. c4 = getcon(4, fn);
  487. c8 = getcon(8, fn);
  488. c16 = getcon(16, fn);
  489. ap = i->arg[0];
  490. isint = KBASE(i->cls) == 0;
  491. /* @b [...]
  492. r0 =l add ap, (0 or 4)
  493. nr =l loadsw r0
  494. r1 =w cultw nr, (48 or 176)
  495. jnz r1, @breg, @bstk
  496. @breg
  497. r0 =l add ap, 16
  498. r1 =l loadl r0
  499. lreg =l add r1, nr
  500. r0 =w add nr, (8 or 16)
  501. r1 =l add ap, (0 or 4)
  502. storew r0, r1
  503. @bstk
  504. r0 =l add ap, 8
  505. lstk =l loadl r0
  506. r1 =l add lstk, 8
  507. storel r1, r0
  508. @b0
  509. %loc =l phi @breg %lreg, @bstk %lstk
  510. i->to =(i->cls) load %loc
  511. */
  512. loc = newtmp("abi", Kl, fn);
  513. emit(Oload, i->cls, i->to, loc, R);
  514. b0 = split(fn, b);
  515. b0->jmp = b->jmp;
  516. b0->s1 = b->s1;
  517. b0->s2 = b->s2;
  518. if (b->s1)
  519. chpred(b->s1, b, b0);
  520. if (b->s2 && b->s2 != b->s1)
  521. chpred(b->s2, b, b0);
  522. lreg = newtmp("abi", Kl, fn);
  523. nr = newtmp("abi", Kl, fn);
  524. r0 = newtmp("abi", Kw, fn);
  525. r1 = newtmp("abi", Kl, fn);
  526. emit(Ostorew, Kw, R, r0, r1);
  527. emit(Oadd, Kl, r1, ap, isint ? CON_Z : c4);
  528. emit(Oadd, Kw, r0, nr, isint ? c8 : c16);
  529. r0 = newtmp("abi", Kl, fn);
  530. r1 = newtmp("abi", Kl, fn);
  531. emit(Oadd, Kl, lreg, r1, nr);
  532. emit(Oload, Kl, r1, r0, R);
  533. emit(Oadd, Kl, r0, ap, c16);
  534. breg = split(fn, b);
  535. breg->jmp.type = Jjmp;
  536. breg->s1 = b0;
  537. lstk = newtmp("abi", Kl, fn);
  538. r0 = newtmp("abi", Kl, fn);
  539. r1 = newtmp("abi", Kl, fn);
  540. emit(Ostorel, Kw, R, r1, r0);
  541. emit(Oadd, Kl, r1, lstk, c8);
  542. emit(Oload, Kl, lstk, r0, R);
  543. emit(Oadd, Kl, r0, ap, c8);
  544. bstk = split(fn, b);
  545. bstk->jmp.type = Jjmp;
  546. bstk->s1 = b0;
  547. b0->phi = alloc(sizeof *b0->phi);
  548. *b0->phi = (Phi){
  549. .cls = Kl, .to = loc,
  550. .narg = 2,
  551. .blk = vnew(2, sizeof b0->phi->blk[0], PFn),
  552. .arg = vnew(2, sizeof b0->phi->arg[0], PFn),
  553. };
  554. b0->phi->blk[0] = bstk;
  555. b0->phi->blk[1] = breg;
  556. b0->phi->arg[0] = lstk;
  557. b0->phi->arg[1] = lreg;
  558. r0 = newtmp("abi", Kl, fn);
  559. r1 = newtmp("abi", Kw, fn);
  560. b->jmp.type = Jjnz;
  561. b->jmp.arg = r1;
  562. b->s1 = breg;
  563. b->s2 = bstk;
  564. c = getcon(isint ? 48 : 176, fn);
  565. emit(Ocmpw+Ciult, Kw, r1, nr, c);
  566. emit(Oloadsw, Kl, nr, r0, R);
  567. emit(Oadd, Kl, r0, ap, isint ? CON_Z : c4);
  568. }
  569. static void
  570. selvastart(Fn *fn, int fa, Ref ap)
  571. {
  572. Ref r0, r1;
  573. int gp, fp, sp;
  574. gp = ((fa >> 4) & 15) * 8;
  575. fp = 48 + ((fa >> 8) & 15) * 16;
  576. sp = fa >> 12;
  577. r0 = newtmp("abi", Kl, fn);
  578. r1 = newtmp("abi", Kl, fn);
  579. emit(Ostorel, Kw, R, r1, r0);
  580. emit(Oadd, Kl, r1, TMP(RBP), getcon(-176, fn));
  581. emit(Oadd, Kl, r0, ap, getcon(16, fn));
  582. r0 = newtmp("abi", Kl, fn);
  583. r1 = newtmp("abi", Kl, fn);
  584. emit(Ostorel, Kw, R, r1, r0);
  585. emit(Oadd, Kl, r1, TMP(RBP), getcon(sp, fn));
  586. emit(Oadd, Kl, r0, ap, getcon(8, fn));
  587. r0 = newtmp("abi", Kl, fn);
  588. emit(Ostorew, Kw, R, getcon(fp, fn), r0);
  589. emit(Oadd, Kl, r0, ap, getcon(4, fn));
  590. emit(Ostorew, Kw, R, getcon(gp, fn), ap);
  591. }
  592. void
  593. amd64_sysv_abi(Fn *fn)
  594. {
  595. Blk *b;
  596. Ins *i, *i0, *ip;
  597. RAlloc *ral;
  598. int n, fa;
  599. for (b=fn->start; b; b=b->link)
  600. b->visit = 0;
  601. /* lower parameters */
  602. for (b=fn->start, i=b->ins; i<&b->ins[b->nins]; i++)
  603. if (!ispar(i->op))
  604. break;
  605. fa = selpar(fn, b->ins, i);
  606. n = b->nins - (i - b->ins) + (&insb[NIns] - curi);
  607. i0 = alloc(n * sizeof(Ins));
  608. ip = icpy(ip = i0, curi, &insb[NIns] - curi);
  609. ip = icpy(ip, i, &b->ins[b->nins] - i);
  610. b->nins = n;
  611. b->ins = i0;
  612. /* lower calls, returns, and vararg instructions */
  613. ral = 0;
  614. b = fn->start;
  615. do {
  616. if (!(b = b->link))
  617. b = fn->start; /* do it last */
  618. if (b->visit)
  619. continue;
  620. curi = &insb[NIns];
  621. selret(b, fn);
  622. for (i=&b->ins[b->nins]; i!=b->ins;)
  623. switch ((--i)->op) {
  624. default:
  625. emiti(*i);
  626. break;
  627. case Ocall:
  628. for (i0=i; i0>b->ins; i0--)
  629. if (!isarg((i0-1)->op))
  630. break;
  631. selcall(fn, i0, i, &ral);
  632. i = i0;
  633. break;
  634. case Ovastart:
  635. selvastart(fn, fa, i->arg[0]);
  636. break;
  637. case Ovaarg:
  638. selvaarg(fn, b, i);
  639. break;
  640. case Oarg:
  641. case Oargc:
  642. die("unreachable");
  643. }
  644. if (b == fn->start)
  645. for (; ral; ral=ral->link)
  646. emiti(ral->i);
  647. b->nins = &insb[NIns] - curi;
  648. idup(&b->ins, curi, b->nins);
  649. } while (b != fn->start);
  650. if (debug['A']) {
  651. fprintf(stderr, "\n> After ABI lowering:\n");
  652. printfn(fn, stderr);
  653. }
  654. }