cgen.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403
  1. #include "gc.h"
  2. void
  3. cgen(Node *n, int result, Node *nn)
  4. {
  5. Node *l, *r, nod;
  6. int lg, rg, xg, yg, g, o;
  7. long v;
  8. Prog *p1;
  9. if(n == Z || n->type == T)
  10. return;
  11. if(typesuv[n->type->etype]) {
  12. sugen(n, result, nn, n->type->width);
  13. return;
  14. }
  15. if(debug['g']) {
  16. if(result == D_TREE)
  17. prtree(nn, "result");
  18. else
  19. print("result = %R\n", result);
  20. prtree(n, "cgen");
  21. }
  22. l = n->left;
  23. r = n->right;
  24. o = n->op;
  25. if(n->addable >= INDEXED) {
  26. if(result == D_NONE) {
  27. switch(o) {
  28. default:
  29. nullwarn(Z, Z);
  30. break;
  31. case OINDEX:
  32. nullwarn(l, r);
  33. break;
  34. }
  35. return;
  36. }
  37. gmove(n->type, nn->type, D_TREE, n, result, nn);
  38. return;
  39. }
  40. v = 0; /* set */
  41. switch(o) {
  42. default:
  43. diag(n, "unknown op in cgen: %O", o);
  44. break;
  45. case OAS:
  46. if(l->op == OBIT)
  47. goto bitas;
  48. /*
  49. * recursive use of result
  50. */
  51. if(result == D_NONE)
  52. if(l->addable > INDEXED)
  53. if(l->complex < FNX) {
  54. cgen(r, D_TREE, l);
  55. break;
  56. }
  57. /*
  58. * function calls on both sides
  59. */
  60. if(l->complex >= FNX && r->complex >= FNX) {
  61. cgen(r, D_TOS, r);
  62. v = argoff;
  63. lg = regaddr(result);
  64. lcgen(l, lg, Z);
  65. lg |= I_INDIR;
  66. adjsp(v - argoff);
  67. gmove(r->type, l->type, D_TOS, r, lg, l);
  68. if(result != D_NONE)
  69. gmove(l->type, nn->type, lg, l, result, nn);
  70. regfree(lg);
  71. break;
  72. }
  73. rg = D_TREE;
  74. lg = D_TREE;
  75. if(r->complex >= l->complex) {
  76. /*
  77. * right side before left
  78. */
  79. if(result != D_NONE) {
  80. rg = regalloc(n->type, result);
  81. cgen(r, rg, n);
  82. } else
  83. if(r->complex >= FNX || r->addable < INDEXED) {
  84. rg = regalloc(r->type, result);
  85. cgen(r, rg, r);
  86. }
  87. if(l->addable < INDEXED) {
  88. lg = regaddr(lg);
  89. lcgen(l, lg, Z);
  90. lg |= I_INDIR;
  91. }
  92. } else {
  93. /*
  94. * left before right
  95. */
  96. if(l->complex >= FNX || l->addable < INDEXED) {
  97. lg = regaddr(lg);
  98. lcgen(l, lg, Z);
  99. lg |= I_INDIR;
  100. }
  101. if(result != D_NONE) {
  102. rg = regalloc(n->type, result);
  103. cgen(r, rg, n);
  104. } else
  105. if(r->addable < INDEXED) {
  106. rg = regalloc(r->type, result);
  107. cgen(r, rg, r);
  108. }
  109. }
  110. if(result != D_NONE) {
  111. gmove(n->type, l->type, rg, r, lg, l);
  112. gmove(n->type, nn->type, rg, r, result, nn);
  113. } else
  114. gmove(r->type, l->type, rg, r, lg, l);
  115. regfree(lg);
  116. regfree(rg);
  117. break;
  118. bitas:
  119. n = l->left;
  120. rg = regalloc(tfield, result);
  121. if(l->complex >= r->complex) {
  122. lg = regaddr(D_NONE);
  123. lcgen(n, lg, Z);
  124. lg |= I_INDIR;
  125. cgen(r, rg, r);
  126. } else {
  127. cgen(r, rg, r);
  128. lg = regaddr(D_NONE);
  129. lcgen(n, lg, Z);
  130. lg |= I_INDIR;
  131. }
  132. g = regalloc(n->type, D_NONE);
  133. gmove(l->type, l->type, lg, l, g, l);
  134. bitstore(l, rg, lg, g, result, nn);
  135. break;
  136. case OBIT:
  137. if(result == D_NONE) {
  138. nullwarn(l, Z);
  139. break;
  140. }
  141. g = bitload(n, D_NONE, D_NONE, result, nn);
  142. gopcode(OAS, nn->type, g, n, result, nn);
  143. regfree(g);
  144. break;
  145. case ODOT:
  146. sugen(l, D_TREE, nodrat, l->type->width);
  147. if(result != D_NONE) {
  148. warn(n, "non-interruptable temporary");
  149. nod = *nodrat;
  150. if(!r || r->op != OCONST) {
  151. diag(n, "DOT and no offset");
  152. break;
  153. }
  154. nod.xoffset += r->vconst;
  155. nod.type = n->type;
  156. cgen(&nod, result, nn);
  157. }
  158. break;
  159. case OASLDIV:
  160. case OASLMOD:
  161. case OASDIV:
  162. case OASMOD:
  163. if(l->op == OBIT)
  164. goto asbitop;
  165. if(typefd[n->type->etype])
  166. goto asbinop;
  167. rg = D_TREE;
  168. if(l->complex >= FNX || r->complex >= FNX) {
  169. rg = D_TOS;
  170. cgen(r, rg, r);
  171. v = argoff;
  172. } else
  173. if(r->addable < INDEXED) {
  174. rg = regalloc(n->type, D_NONE);
  175. cgen(r, rg, r);
  176. }
  177. lg = D_TREE;
  178. if(!simplv(l)) {
  179. lg = regaddr(D_NONE);
  180. lcgen(l, lg, Z); /* destroys register optimization */
  181. lg |= I_INDIR;
  182. }
  183. g = regpair(result);
  184. gmove(l->type, n->type, lg, l, g, n);
  185. if(rg == D_TOS)
  186. adjsp(v - argoff);
  187. gopcode(o, n->type, rg, r, g, n);
  188. if(o == OASLMOD || o == OASMOD)
  189. gmove(n->type, l->type, g+1, n, lg, l);
  190. else
  191. gmove(n->type, l->type, g, n, lg, l);
  192. if(result != D_NONE)
  193. if(o == OASLMOD || o == OASMOD)
  194. gmove(n->type, nn->type, g+1, n, result, nn);
  195. else
  196. gmove(n->type, nn->type, g, n, result, nn);
  197. regfree(g);
  198. regfree(g+1);
  199. regfree(lg);
  200. regfree(rg);
  201. break;
  202. case OASXOR:
  203. case OASAND:
  204. case OASOR:
  205. if(l->op == OBIT)
  206. goto asbitop;
  207. if(l->complex >= FNX ||
  208. l->addable < INDEXED ||
  209. result != D_NONE ||
  210. typefd[n->type->etype])
  211. goto asbinop;
  212. rg = D_TREE;
  213. if(r->op != OCONST) {
  214. rg = regalloc(n->type, D_NONE);
  215. cgen(r, rg, r);
  216. }
  217. gopcode(o, l->type, rg, r, D_TREE, l);
  218. regfree(rg);
  219. break;
  220. case OASADD:
  221. case OASSUB:
  222. if(l->op == OBIT ||
  223. l->complex >= FNX ||
  224. l->addable < INDEXED ||
  225. result != D_NONE ||
  226. typefd[n->type->etype])
  227. goto asbinop;
  228. v = vconst(r);
  229. if(v > 0 && v <= 8) {
  230. gopcode(o, n->type, D_TREE, r, D_TREE, l);
  231. break;
  232. }
  233. rg = regalloc(n->type, D_NONE);
  234. cgen(r, rg, r);
  235. gopcode(o, n->type, rg, r, D_TREE, l);
  236. regfree(rg);
  237. break;
  238. case OASLSHR:
  239. case OASASHR:
  240. case OASASHL:
  241. if(l->op == OBIT ||
  242. l->complex >= FNX ||
  243. l->addable < INDEXED ||
  244. result != D_NONE ||
  245. typefd[n->type->etype])
  246. goto asbinop;
  247. rg = D_TREE;
  248. v = vconst(r);
  249. if(v <= 0 || v > 8) {
  250. rg = regalloc(n->type, D_NONE);
  251. cgen(r, rg, r);
  252. }
  253. lg = regalloc(n->type, D_NONE);
  254. cgen(l, lg, l);
  255. gopcode(o, n->type, rg, r, lg, l);
  256. gmove(n->type, n->type, lg, l, D_TREE, l);
  257. regfree(lg);
  258. regfree(rg);
  259. break;
  260. case OASLMUL:
  261. case OASMUL:
  262. asbinop:
  263. if(l->op == OBIT)
  264. goto asbitop;
  265. rg = D_TREE;
  266. if(l->complex >= FNX || r->complex >= FNX) {
  267. rg = D_TOS;
  268. cgen(r, rg, r);
  269. v = argoff;
  270. } else
  271. if(r->addable < INDEXED) {
  272. rg = regalloc(n->type, D_NONE);
  273. cgen(r, rg, r);
  274. } else {
  275. if(o == OASLSHR || o == OASASHR || o == OASASHL) {
  276. v = vconst(r);
  277. if(v <= 0 || v > 8) {
  278. rg = regalloc(n->type, D_NONE);
  279. cgen(r, rg, r);
  280. }
  281. }
  282. }
  283. lg = D_TREE;
  284. if(!simplv(l)) {
  285. lg = regaddr(D_NONE);
  286. lcgen(l, lg, Z); /* destroys register optimization */
  287. lg |= I_INDIR;
  288. }
  289. g = regalloc(n->type, result);
  290. gmove(l->type, n->type, lg, l, g, n);
  291. if(rg == D_TOS)
  292. adjsp(v - argoff);
  293. if(o == OASXOR)
  294. if(rg == D_TREE) {
  295. rg = regalloc(n->type, D_NONE);
  296. cgen(r, rg, r);
  297. }
  298. if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL)
  299. if(rg == D_TOS) {
  300. rg = regalloc(n->type, D_NONE);
  301. gmove(n->type, n->type, D_TOS, n, rg, n);
  302. }
  303. gopcode(o, n->type, rg, r, g, n);
  304. gmove(n->type, l->type, g, n, lg, l);
  305. if(result != D_NONE)
  306. gmove(n->type, nn->type, g, n, result, nn);
  307. regfree(g);
  308. regfree(lg);
  309. regfree(rg);
  310. break;
  311. asbitop:
  312. rg = regaddr(D_NONE);
  313. lg = regalloc(tfield, D_NONE);
  314. if(l->complex >= r->complex) {
  315. g = bitload(l, lg, rg, result, nn);
  316. xg = regalloc(r->type, D_NONE);
  317. cgen(r, xg, nn);
  318. } else {
  319. xg = regalloc(r->type, D_NONE);
  320. cgen(r, xg, nn);
  321. g = bitload(l, lg, rg, result, nn);
  322. }
  323. if(!typefd[n->type->etype]) {
  324. if(o == OASLDIV || o == OASDIV) {
  325. yg = regpair(result);
  326. gmove(tfield, n->type, g, l, yg, n);
  327. gopcode(o, n->type, xg, r, yg, n);
  328. gmove(n->type, tfield, yg, n, g, l);
  329. regfree(yg);
  330. regfree(yg+1);
  331. regfree(xg);
  332. bitstore(l, g, rg, lg, D_NONE, nn);
  333. break;
  334. }
  335. if(o == OASLMOD || o == OASMOD) {
  336. yg = regpair(result);
  337. gmove(tfield, n->type, g, l, yg, n);
  338. gopcode(o, n->type, xg, r, yg, n);
  339. gmove(n->type, tfield, yg+1, n, g, l);
  340. regfree(yg);
  341. regfree(yg+1);
  342. regfree(xg);
  343. bitstore(l, g, rg, lg, D_NONE, nn);
  344. break;
  345. }
  346. }
  347. yg = regalloc(n->type, result);
  348. gmove(tfield, n->type, g, l, yg, n);
  349. gopcode(o, n->type, xg, r, yg, n);
  350. gmove(n->type, tfield, yg, n, g, l);
  351. regfree(yg);
  352. regfree(xg);
  353. bitstore(l, g, rg, lg, D_NONE, nn);
  354. break;
  355. case OCAST:
  356. if(result == D_NONE) {
  357. nullwarn(l, Z);
  358. break;
  359. }
  360. lg = result;
  361. if(l->complex >= FNX)
  362. lg = regret(l->type);
  363. lg = eval(l, lg);
  364. if(nocast(l->type, n->type)) {
  365. gmove(n->type, nn->type, lg, l, result, nn);
  366. regfree(lg);
  367. break;
  368. }
  369. if(nocast(n->type, nn->type)) {
  370. gmove(l->type, n->type, lg, l, result, nn);
  371. regfree(lg);
  372. break;
  373. }
  374. rg = regalloc(n->type, result);
  375. gmove(l->type, n->type, lg, l, rg, n);
  376. gmove(n->type, nn->type, rg, n, result, nn);
  377. regfree(rg);
  378. regfree(lg);
  379. break;
  380. case OCOND:
  381. doinc(l, PRE);
  382. boolgen(l, 1, D_NONE, Z, l);
  383. p1 = p;
  384. inargs++;
  385. doinc(r->left, PRE);
  386. cgen(r->left, result, nn);
  387. doinc(r->left, POST);
  388. gbranch(OGOTO);
  389. patch(p1, pc);
  390. p1 = p;
  391. doinc(r->right, PRE);
  392. cgen(r->right, result, nn);
  393. doinc(r->right, POST);
  394. patch(p1, pc);
  395. inargs--;
  396. break;
  397. case OIND:
  398. if(result == D_NONE) {
  399. nullwarn(l, Z);
  400. break;
  401. }
  402. lg = nodalloc(types[TIND], result, &nod);
  403. nod.lineno = n->lineno;
  404. if(l->op == OADD) {
  405. if(l->left->op == OCONST) {
  406. nod.xoffset += l->left->vconst;
  407. l = l->right;
  408. } else
  409. if(l->right->op == OCONST) {
  410. nod.xoffset += l->right->vconst;
  411. l = l->left;
  412. }
  413. }
  414. cgen(l, lg, l);
  415. gmove(n->type, nn->type, D_TREE, &nod, result, nn);
  416. regfree(lg);
  417. break;
  418. case OFUNC:
  419. v = argoff;
  420. inargs++;
  421. gargs(r);
  422. lg = D_TREE;
  423. if(l->addable < INDEXED) {
  424. lg = regaddr(result);
  425. lcgen(l, lg, Z);
  426. lg |= I_INDIR;
  427. }
  428. inargs--;
  429. doinc(r, POST);
  430. doinc(l, POST);
  431. gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
  432. regfree(lg);
  433. if(inargs)
  434. adjsp(v - argoff);
  435. if(result != D_NONE) {
  436. lg = regret(n->type);
  437. gmove(n->type, nn->type, lg, n, result, nn);
  438. }
  439. break;
  440. case OLDIV:
  441. case OLMOD:
  442. case ODIV:
  443. case OMOD:
  444. if(result == D_NONE) {
  445. nullwarn(l, r);
  446. break;
  447. }
  448. if(typefd[n->type->etype])
  449. goto binop;
  450. if(r->addable >= INDEXED && r->complex < FNX) {
  451. lg = regpair(result);
  452. cgen(l, lg, l);
  453. rg = D_TREE;
  454. } else {
  455. cgen(r, D_TOS, r);
  456. v = argoff;
  457. lg = regpair(result);
  458. cgen(l, lg, l);
  459. adjsp(v - argoff);
  460. rg = D_TOS;
  461. }
  462. gopcode(o, n->type, rg, r, lg, l);
  463. if(o == OMOD || o == OLMOD)
  464. gmove(l->type, nn->type, lg+1, l, result, nn);
  465. else
  466. gmove(l->type, nn->type, lg, l, result, nn);
  467. regfree(lg);
  468. regfree(lg+1);
  469. break;
  470. case OMUL:
  471. case OLMUL:
  472. if(l->op == OCONST)
  473. if(mulcon(r, l, result, nn))
  474. break;
  475. if(r->op == OCONST)
  476. if(mulcon(l, r, result, nn))
  477. break;
  478. if(debug['M'])
  479. print("%L multiply\n", n->lineno);
  480. goto binop;
  481. case OAND:
  482. if(r->op == OCONST)
  483. if(typeil[n->type->etype])
  484. if(l->op == OCAST) {
  485. if(typec[l->left->type->etype])
  486. if(!(r->vconst & ~0xff)) {
  487. l = l->left;
  488. goto binop;
  489. }
  490. if(typeh[l->left->type->etype])
  491. if(!(r->vconst & ~0xffff)) {
  492. l = l->left;
  493. goto binop;
  494. }
  495. }
  496. goto binop;
  497. case OADD:
  498. if(result == D_TOS)
  499. if(r->addable >= INDEXED)
  500. if(l->op == OCONST)
  501. if(typeil[l->type->etype]) {
  502. v = l->vconst;
  503. if(v > -32768 && v < 32768) {
  504. rg = regaddr(D_NONE);
  505. gmove(r->type, r->type, D_TREE, r, rg, r);
  506. gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r);
  507. p->to.offset = v;
  508. p->to.type |= I_INDIR;
  509. regfree(rg);
  510. break;
  511. }
  512. }
  513. case OSUB:
  514. if(result == D_TOS)
  515. if(l->addable >= INDEXED)
  516. if(r->op == OCONST)
  517. if(typeil[r->type->etype]) {
  518. v = r->vconst;
  519. if(v > -32768 && v < 32768) {
  520. if(n->op == OSUB)
  521. v = -v;
  522. lg = regaddr(D_NONE);
  523. gmove(l->type, l->type, D_TREE, l, lg, l);
  524. gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l);
  525. p->to.offset = v;
  526. p->to.type |= I_INDIR;
  527. regfree(lg);
  528. break;
  529. }
  530. }
  531. goto binop;
  532. case OOR:
  533. case OXOR:
  534. binop:
  535. if(result == D_NONE) {
  536. nullwarn(l, r);
  537. break;
  538. }
  539. if(l->complex >= FNX && r->complex >= FNX) {
  540. cgen(r, D_TOS, r);
  541. v = argoff;
  542. lg = regalloc(l->type, result);
  543. cgen(l, lg, l);
  544. adjsp(v - argoff);
  545. if(o == OXOR) {
  546. rg = regalloc(r->type, D_NONE);
  547. gmove(r->type, r->type, D_TOS, r, rg, r);
  548. gopcode(o, n->type, rg, r, lg, l);
  549. regfree(rg);
  550. } else
  551. gopcode(o, n->type, D_TOS, r, lg, l);
  552. gmove(n->type, nn->type, lg, l, result, nn);
  553. regfree(lg);
  554. break;
  555. }
  556. if(l->complex >= r->complex) {
  557. if(l->op == OADDR && (o == OADD || o == OSUB))
  558. lg = regaddr(result);
  559. else
  560. lg = regalloc(l->type, result);
  561. cgen(l, lg, l);
  562. rg = eval(r, D_NONE);
  563. } else {
  564. rg = regalloc(r->type, D_NONE);
  565. cgen(r, rg, r);
  566. lg = regalloc(l->type, result);
  567. cgen(l, lg, l);
  568. }
  569. if(o == OXOR) {
  570. if(rg == D_TREE) {
  571. rg = regalloc(r->type, D_NONE);
  572. cgen(r, rg, r);
  573. }
  574. if(rg == D_TOS) {
  575. rg = regalloc(r->type, D_NONE);
  576. gmove(r->type, r->type, D_TOS, r, rg, r);
  577. }
  578. }
  579. gopcode(o, n->type, rg, r, lg, l);
  580. gmove(n->type, nn->type, lg, l, result, nn);
  581. regfree(lg);
  582. regfree(rg);
  583. break;
  584. case OASHL:
  585. if(r->op == OCONST)
  586. if(shlcon(l, r, result, nn))
  587. break;
  588. case OLSHR:
  589. case OASHR:
  590. if(result == D_NONE) {
  591. nullwarn(l, r);
  592. break;
  593. }
  594. if(l->complex >= FNX && r->complex >= FNX) {
  595. cgen(r, D_TOS, r);
  596. v = argoff;
  597. lg = regalloc(l->type, result);
  598. cgen(l, lg, l);
  599. adjsp(v - argoff);
  600. rg = regalloc(r->type, D_NONE);
  601. gopcode(OAS, r->type, D_TOS, r, rg, r);
  602. gopcode(n->op, n->type, rg, r, lg, l);
  603. gmove(n->type, nn->type, lg, l, result, nn);
  604. regfree(lg);
  605. regfree(rg);
  606. break;
  607. }
  608. if(l->complex >= r->complex) {
  609. lg = regalloc(l->type, result);
  610. cgen(l, lg, l);
  611. v = vconst(r);
  612. if(v <= 0 || v > 8) {
  613. rg = regalloc(r->type, D_NONE);
  614. cgen(r, rg, r);
  615. } else
  616. rg = eval(r, D_NONE);
  617. } else {
  618. rg = regalloc(r->type, D_NONE);
  619. cgen(r, rg, r);
  620. lg = regalloc(l->type, result);
  621. cgen(l, lg, l);
  622. }
  623. gopcode(o, n->type, rg, r, lg, l);
  624. gmove(n->type, nn->type, lg, l, result, nn);
  625. regfree(lg);
  626. regfree(rg);
  627. break;
  628. case ONEG:
  629. case OCOM:
  630. if(result == D_NONE) {
  631. nullwarn(l, Z);
  632. break;
  633. }
  634. lg = regalloc(l->type, result);
  635. cgen(l, lg, l);
  636. gopcode(o, l->type, D_NONE, Z, lg, l);
  637. gmove(n->type, nn->type, lg, l, result, nn);
  638. regfree(lg);
  639. break;
  640. case OADDR:
  641. if(result == D_NONE) {
  642. nullwarn(l, Z);
  643. break;
  644. }
  645. if(l->op == OINDEX && l->scale == 4 && result != D_TOS) {
  646. /* index scaled by 1, add is better */
  647. nod = *l;
  648. nod.op = OADD;
  649. nod.addable = 0;
  650. cgen(&nod, result, nn);
  651. break;
  652. }
  653. lcgen(l, result, nn);
  654. break;
  655. case OEQ:
  656. case ONE:
  657. case OLE:
  658. case OLT:
  659. case OGE:
  660. case OGT:
  661. case OLO:
  662. case OLS:
  663. case OHI:
  664. case OHS:
  665. if(result == D_NONE) {
  666. nullwarn(l, r);
  667. break;
  668. }
  669. boolgen(n, 1, result, nn, Z);
  670. break;
  671. case OANDAND:
  672. case OOROR:
  673. boolgen(n, 1, result, nn, Z);
  674. if(result == D_NONE)
  675. patch(p, pc);
  676. break;
  677. case OCOMMA:
  678. cgen(l, D_NONE, l);
  679. doinc(l, POST);
  680. doinc(r, PRE);
  681. cgen(r, result, nn);
  682. break;
  683. case ONOT:
  684. if(result == D_NONE) {
  685. nullwarn(l, Z);
  686. break;
  687. }
  688. boolgen(n, 1, result, nn, Z);
  689. break;
  690. case OPOSTINC:
  691. case OPOSTDEC:
  692. v = 1;
  693. if(l->type->etype == TIND)
  694. v = l->type->link->width;
  695. if(o == OPOSTDEC)
  696. v = -v;
  697. if(l->op == OBIT)
  698. goto bitinc;
  699. if(nn == Z)
  700. goto pre;
  701. lg = D_TREE;
  702. if(l->addable < INDEXED) {
  703. lg = regaddr(D_NONE);
  704. lcgen(l, lg, Z);
  705. lg |= I_INDIR;
  706. }
  707. if(result != D_NONE)
  708. gmove(l->type, nn->type, lg, l, result, nn);
  709. if(typefd[n->type->etype]) {
  710. rg = regalloc(n->type, D_NONE);
  711. gmove(l->type, l->type, lg, l, rg, l);
  712. gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
  713. gmove(l->type, l->type, rg, l, lg, l);
  714. regfree(rg);
  715. } else {
  716. if(v < 0)
  717. gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
  718. else
  719. gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
  720. }
  721. regfree(lg);
  722. break;
  723. case OPREINC:
  724. case OPREDEC:
  725. v = 1;
  726. if(l->type->etype == TIND)
  727. v = l->type->link->width;
  728. if(o == OPREDEC)
  729. v = -v;
  730. if(l->op == OBIT)
  731. goto bitinc;
  732. pre:
  733. lg = D_TREE;
  734. if(l->addable < INDEXED) {
  735. lg = regaddr(D_NONE);
  736. lcgen(l, lg, Z);
  737. lg |= I_INDIR;
  738. }
  739. if(typefd[n->type->etype]) {
  740. rg = regalloc(n->type, D_NONE);
  741. gmove(l->type, l->type, lg, l, rg, l);
  742. gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
  743. gmove(l->type, l->type, rg, l, lg, l);
  744. regfree(rg);
  745. } else {
  746. if(v < 0)
  747. gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
  748. else
  749. gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
  750. }
  751. if(result != D_NONE)
  752. gmove(l->type, nn->type, lg, l, result, nn);
  753. regfree(lg);
  754. break;
  755. bitinc:
  756. rg = regaddr(D_NONE);
  757. lg = regalloc(tfield, D_NONE);
  758. if(result != D_NONE && (o == OPOSTINC || o == OPOSTDEC)) {
  759. g = bitload(l, lg, rg, D_NONE, nn);
  760. if(nn != Z)
  761. gmove(l->type, nn->type, g, l, result, nn);
  762. if(v < 0)
  763. gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
  764. else
  765. gopcode(o, n->type, D_CONST, nodconst(v), g, n);
  766. bitstore(l, g, rg, lg, D_NONE, nn);
  767. break;
  768. }
  769. g = bitload(l, lg, rg, result, nn);
  770. if(v < 0)
  771. gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
  772. else
  773. gopcode(o, n->type, D_CONST, nodconst(v), g, n);
  774. if(result != D_NONE)
  775. gmove(l->type, nn->type, g, l, result, nn);
  776. bitstore(l, g, rg, lg, D_NONE, nn);
  777. break;
  778. }
  779. }
  780. void
  781. lcgen(Node *n, int result, Node *nn)
  782. {
  783. Node rn;
  784. Prog *p1;
  785. int lg;
  786. if(n == Z || n->type == T)
  787. return;
  788. if(debug['g']) {
  789. if(result == D_TREE)
  790. prtree(nn, "result");
  791. else
  792. print("result = %R\n", result);
  793. prtree(n, "lcgen");
  794. }
  795. if(nn == Z) {
  796. nn = &rn;
  797. nn->type = types[TIND];
  798. }
  799. switch(n->op) {
  800. case OCOMMA:
  801. cgen(n->left, D_NONE, n->left);
  802. doinc(n->left, POST);
  803. doinc(n->right, PRE);
  804. lcgen(n->right, result, nn);
  805. break;
  806. case OCOND:
  807. doinc(n->left, PRE);
  808. boolgen(n->left, 1, D_NONE, Z, n->left);
  809. p1 = p;
  810. inargs++;
  811. doinc(n->right->left, PRE);
  812. lcgen(n->right->left, result, nn);
  813. doinc(n->right->left, POST);
  814. gbranch(OGOTO);
  815. patch(p1, pc);
  816. p1 = p;
  817. doinc(n->right->right, PRE);
  818. lcgen(n->right->right, result, nn);
  819. doinc(n->right->right, POST);
  820. patch(p1, pc);
  821. inargs--;
  822. break;
  823. case OIND:
  824. if(n->addable >= INDEXED) {
  825. if(result >= D_A0 && result < D_A0+NREG) {
  826. gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
  827. break;
  828. }
  829. if(result == D_TOS) {
  830. gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
  831. break;
  832. }
  833. }
  834. cgen(n->left, result, nn);
  835. break;
  836. default:
  837. if(n->addable < INDEXED) {
  838. diag(n, "unknown op in lcgen: %O", n->op);
  839. break;
  840. }
  841. if(result >= D_A0 && result < D_A0+NREG) {
  842. gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
  843. break;
  844. }
  845. if(result == D_TOS) {
  846. gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
  847. break;
  848. }
  849. lg = regaddr(result);
  850. gopcode(OADDR, types[TLONG], D_TREE, n, lg, nn);
  851. gopcode(OAS, nn->type, lg, nn, result, nn);
  852. regfree(lg);
  853. break;
  854. }
  855. }
  856. void
  857. bcgen(Node *n, int true)
  858. {
  859. boolgen(n, true, D_NONE, Z, Z);
  860. }
  861. void
  862. boolgen(Node *n, int true, int result, Node *nn, Node *post)
  863. {
  864. Prog *p1, *p2;
  865. Node *l, *r;
  866. int lg, rg, fp, o;
  867. long v;
  868. if(debug['g']) {
  869. if(result == D_TREE)
  870. prtree(nn, "result");
  871. else
  872. print("result = %R\n", result);
  873. prtree(n, "boolgen");
  874. }
  875. l = n->left;
  876. r = n->right;
  877. switch(n->op) {
  878. default:
  879. lg = eval(n, result);
  880. if(lg >= D_A0 && lg < D_A0+NREG) {
  881. rg = regalloc(types[TLONG], D_NONE);
  882. gopcode(OAS, types[TLONG], lg, n, rg, Z);
  883. regfree(rg);
  884. } else
  885. gopcode(OTST, n->type, D_NONE, Z, lg, n);
  886. regfree(lg);
  887. o = ONE;
  888. fp = typefd[n->type->etype];
  889. goto genbool;
  890. case OCONST:
  891. fp = vconst(n);
  892. if(!true)
  893. fp = !fp;
  894. gbranch(OGOTO);
  895. if(fp) {
  896. p1 = p;
  897. gbranch(OGOTO);
  898. patch(p1, pc);
  899. }
  900. goto com;
  901. case ONOT:
  902. boolgen(l, !true, result, nn, post);
  903. break;
  904. case OCOND:
  905. doinc(l, PRE);
  906. boolgen(l, 1, D_NONE, Z, l);
  907. p1 = p;
  908. inargs++;
  909. doinc(r->left, PRE);
  910. boolgen(r->left, true, result, nn, r->left);
  911. if(result != D_NONE) {
  912. doinc(r->left, POST);
  913. gbranch(OGOTO);
  914. patch(p1, pc);
  915. p1 = p;
  916. doinc(r->right, PRE);
  917. boolgen(r->right, !true, result, nn, r->right);
  918. doinc(r->right, POST);
  919. patch(p1, pc);
  920. inargs--;
  921. break;
  922. }
  923. p2 = p;
  924. gbranch(OGOTO);
  925. patch(p1, pc);
  926. p1 = p;
  927. doinc(r->right, PRE);
  928. boolgen(r->right, !true, result, nn, r->right);
  929. patch(p2, pc);
  930. p2 = p;
  931. if(doinc(post, POST|TEST)) {
  932. lg = regalloc(types[TSHORT], D_NONE);
  933. gopcode(OAS, types[TSHORT], D_CCR, Z, lg, Z);
  934. doinc(post, POST);
  935. gopcode(OAS, types[TSHORT], lg, Z, D_CCR, Z);
  936. regfree(lg);
  937. }
  938. gbranch(OGOTO);
  939. patch(p1, pc);
  940. patch(p2, pc);
  941. inargs--;
  942. goto com;
  943. case OANDAND:
  944. if(!true)
  945. goto caseor;
  946. caseand:
  947. doinc(l, PRE);
  948. boolgen(l, true, D_NONE, Z, l);
  949. p1 = p;
  950. inargs++;
  951. doinc(r, PRE);
  952. boolgen(r, !true, D_NONE, Z, r);
  953. p2 = p;
  954. patch(p1, pc);
  955. gbranch(OGOTO);
  956. patch(p2, pc);
  957. inargs--;
  958. goto com;
  959. case OOROR:
  960. if(!true)
  961. goto caseand;
  962. caseor:
  963. doinc(l, PRE);
  964. boolgen(l, !true, D_NONE, Z, l);
  965. p1 = p;
  966. inargs++;
  967. doinc(r, PRE);
  968. boolgen(r, !true, D_NONE, Z, r);
  969. p2 = p;
  970. gbranch(OGOTO);
  971. patch(p1, pc);
  972. patch(p2, pc);
  973. inargs--;
  974. goto com;
  975. case OEQ:
  976. case ONE:
  977. if(vconst(l) == 0) {
  978. if(n->op == ONE) {
  979. boolgen(r, true, result, nn, post);
  980. break;
  981. }
  982. boolgen(r, !true, result, nn, post);
  983. break;
  984. }
  985. case OLE:
  986. case OLT:
  987. case OGE:
  988. case OGT:
  989. case OHI:
  990. case OHS:
  991. case OLO:
  992. case OLS:
  993. fp = typefd[r->type->etype];
  994. if(l->op == OCONST) {
  995. v = vconst(l);
  996. if(v == 0) { /* tst instruction */
  997. o = invrel[relindex(n->op)];
  998. rg = eval(r, result);
  999. gopcode(OTST, r->type, D_NONE, Z, rg, r);
  1000. regfree(rg);
  1001. goto genbool;
  1002. }
  1003. if(!fp) { /* cmpi and movq, saves about .5% both time and space */
  1004. if(v < 128 && v >= -128 &&
  1005. ewidth[r->type->etype] == SZ_LONG) {
  1006. rg = eval(r, result);
  1007. lg = regalloc(l->type, D_NONE);
  1008. cgen(l, lg, l);
  1009. o = n->op;
  1010. gopcode(o, l->type, lg, l, rg, r);
  1011. regfree(lg);
  1012. regfree(rg);
  1013. goto genbool;
  1014. }
  1015. o = invrel[relindex(n->op)];
  1016. rg = eval(r, result);
  1017. gopcode(o, r->type, rg, r, D_TREE, l);
  1018. regfree(rg);
  1019. goto genbool;
  1020. }
  1021. }
  1022. lg = D_TOS;
  1023. if(r->complex < FNX)
  1024. lg = regalloc(l->type, lg);
  1025. cgen(l, lg, l);
  1026. v = argoff;
  1027. rg = eval(r, result);
  1028. if(lg == D_TOS) {
  1029. adjsp(v - argoff);
  1030. lg = regalloc(l->type, lg);
  1031. gopcode(OAS, l->type, D_TOS, l, lg, l);
  1032. }
  1033. o = n->op;
  1034. gopcode(o, l->type, lg, l, rg, r);
  1035. regfree(lg);
  1036. regfree(rg);
  1037. genbool:
  1038. if(true)
  1039. o = comrel[relindex(o)];
  1040. if(doinc(post, POST|TEST)) {
  1041. lg = regalloc(types[TSHORT], D_NONE);
  1042. gopcode(OAS, types[TSHORT], D_CCR, Z, lg, Z);
  1043. doinc(post, POST);
  1044. gopcode(OAS, types[TSHORT], lg, Z, D_CCR, Z);
  1045. regfree(lg);
  1046. }
  1047. gbranch(o);
  1048. if(fp)
  1049. fpbranch();
  1050. com:
  1051. if(result == D_NONE)
  1052. break;
  1053. p1 = p;
  1054. gopcode(OAS, nn->type, D_CONST, nodconst(1), result, nn);
  1055. gbranch(OGOTO);
  1056. p2 = p;
  1057. patch(p1, pc);
  1058. gopcode(OAS, nn->type, D_CONST, nodconst(0), result, nn);
  1059. patch(p2, pc);
  1060. break;
  1061. }
  1062. }
  1063. void
  1064. sugen(Node *n, int result, Node *nn, long w)
  1065. {
  1066. long s, v, o;
  1067. int lg, rg, ng;
  1068. Prog *p1;
  1069. Node *l, *r, nod;
  1070. Type *t;
  1071. if(n == Z || n->type == T)
  1072. return;
  1073. if(debug['g']) {
  1074. if(result == D_TREE)
  1075. prtree(nn, "result");
  1076. else
  1077. print("result = %R width = %ld\n", result, w);
  1078. prtree(n, "sugen");
  1079. }
  1080. s = argoff;
  1081. if(result == D_TREE) {
  1082. if(nn == nodrat)
  1083. if(w > nrathole)
  1084. nrathole = w;
  1085. }
  1086. if(n->addable >= INDEXED && n->op != OCONST)
  1087. goto copy;
  1088. switch(n->op) {
  1089. default:
  1090. diag(n, "unknown op in sugen: %O", n->op);
  1091. break;
  1092. case OCONST:
  1093. if(n->type && typev[n->type->etype]) {
  1094. if(result == D_NONE) {
  1095. nullwarn(n->left, Z);
  1096. break;
  1097. }
  1098. lg = regaddr(D_NONE);
  1099. if(result == D_TOS) {
  1100. adjsp(s - argoff + w);
  1101. gopcode(OADDR, types[TIND], result, nn, lg, n);
  1102. } else
  1103. if(result == D_TREE) {
  1104. lcgen(nn, lg, Z);
  1105. } else
  1106. diag(n, "unknown su result: %R", result);
  1107. gopcode(OAS, types[TLONG], D_CONST, nodconst((long)(n->vconst>>32)),
  1108. lg|I_INDINC, n);
  1109. gopcode(OAS, types[TLONG], D_CONST, nodconst((long)(n->vconst)),
  1110. lg|I_INDINC, n);
  1111. regfree(lg);
  1112. break;
  1113. }
  1114. goto copy;
  1115. case ODOT:
  1116. l = n->left;
  1117. sugen(l, D_TREE, nodrat, l->type->width);
  1118. if(result != D_NONE) {
  1119. warn(n, "non-interruptable temporary");
  1120. nod = *nodrat;
  1121. r = n->right;
  1122. if(!r || r->op != OCONST) {
  1123. diag(n, "DOT and no offset");
  1124. break;
  1125. }
  1126. nod.xoffset += r->vconst;
  1127. nod.type = n->type;
  1128. sugen(&nod, result, nn, w);
  1129. }
  1130. break;
  1131. case OIND:
  1132. if(result == D_NONE) {
  1133. nullwarn(n->left, Z);
  1134. break;
  1135. }
  1136. goto copy;
  1137. case OSTRUCT:
  1138. lg = nodalloc(types[TIND], result, &nod);
  1139. nod.lineno = n->lineno;
  1140. if(result == D_TREE)
  1141. lcgen(nn, lg, Z);
  1142. else
  1143. if(result == D_TOS) {
  1144. adjsp(s - argoff + w);
  1145. gopcode(OADDR, types[TIND], result, nn, lg, n);
  1146. } else
  1147. diag(n, "unknown su result: %R", result);
  1148. o = 0;
  1149. r = n->left;
  1150. for(t = n->type->link; t != T; t = t->down) {
  1151. l = r;
  1152. if(r->op == OLIST) {
  1153. l = r->left;
  1154. r = r->right;
  1155. }
  1156. nod.type = t;
  1157. if(l->complex < FNX) {
  1158. nod.xoffset = 0;
  1159. if(o != t->offset) {
  1160. gopcode(OADD, types[TIND], D_CONST,
  1161. nodconst(t->offset-o), lg, Z);
  1162. o = t->offset;
  1163. }
  1164. cgen(l, D_TREE, &nod);
  1165. continue;
  1166. }
  1167. nod.xoffset = t->offset - o;
  1168. gopcode(OAS, types[TIND], lg, Z, D_TOS, Z);
  1169. s = argoff;
  1170. if(typesuv[t->etype]) {
  1171. sugen(l, D_TREE, nodrat, t->width);
  1172. adjsp(s - argoff);
  1173. gopcode(OAS, types[TIND], D_TOS, Z, lg, Z);
  1174. warn(n, "non-interruptable temporary");
  1175. sugen(nodrat, D_TREE, &nod, t->width);
  1176. continue;
  1177. }
  1178. rg = regalloc(t, D_NONE);
  1179. cgen(l, rg, l);
  1180. adjsp(s - argoff);
  1181. gopcode(OAS, types[TIND], D_TOS, Z, lg, Z);
  1182. gopcode(OAS, t, rg, Z, D_TREE, &nod);
  1183. regfree(rg);
  1184. }
  1185. regfree(lg);
  1186. break;
  1187. case OAS:
  1188. if(result == D_NONE) {
  1189. sugen(n->right, D_TREE, n->left, w);
  1190. break;
  1191. }
  1192. sugen(n->right, D_TREE, nodrat, w); /* could do better */
  1193. warn(n, "non-interruptable temporary");
  1194. sugen(nodrat, D_TREE, n->left, w);
  1195. sugen(nodrat, result, nn, w);
  1196. break;
  1197. case OFUNC:
  1198. if(result == D_NONE) {
  1199. sugen(n, D_TREE, nodrat, w);
  1200. break;
  1201. }
  1202. inargs++;
  1203. /* prepare zero-th arg: address of result */
  1204. if(result == D_TOS) {
  1205. adjsp(s - argoff + w);
  1206. v = argoff;
  1207. gargs(n->right);
  1208. gopcode(OADDR, types[TSHORT], D_NONE, nn, result, nn);
  1209. p->to.type = D_STACK;
  1210. p->to.offset = argoff - v;
  1211. } else
  1212. if(result == D_TREE) {
  1213. v = argoff;
  1214. gargs(n->right);
  1215. if(nn->complex >= FNX) {
  1216. rg = regalloc(types[TIND], regret(types[TIND]));
  1217. lcgen(nn, rg, Z);
  1218. gopcode(OAS, types[TIND], rg, Z, D_TOS, Z);
  1219. regfree(rg);
  1220. } else
  1221. lcgen(nn, D_TOS, Z);
  1222. } else {
  1223. diag(n, "unknown result in FUNC sugen");
  1224. break;
  1225. }
  1226. argoff += types[TIND]->width;
  1227. l = n->left;
  1228. lg = D_TREE;
  1229. if(l->addable < INDEXED) {
  1230. lg = regaddr(result);
  1231. lcgen(l, lg, Z);
  1232. lg |= I_INDIR;
  1233. }
  1234. inargs--;
  1235. doinc(n->right, POST);
  1236. doinc(n->left, POST);
  1237. gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
  1238. regfree(lg);
  1239. if(inargs)
  1240. adjsp(v - argoff);
  1241. break;
  1242. case OCOND:
  1243. doinc(n->left, PRE);
  1244. boolgen(n->left, 1, D_NONE, Z, n->left);
  1245. p1 = p;
  1246. inargs++;
  1247. doinc(n->right->left, PRE);
  1248. sugen(n->right->left, result, nn, w);
  1249. doinc(n->right->left, POST);
  1250. gbranch(OGOTO);
  1251. patch(p1, pc);
  1252. p1 = p;
  1253. doinc(n->right->right, PRE);
  1254. sugen(n->right->right, result, nn, w);
  1255. doinc(n->right->right, POST);
  1256. patch(p1, pc);
  1257. inargs--;
  1258. break;
  1259. case OCOMMA:
  1260. cgen(n->left, D_NONE, n->left);
  1261. doinc(n->left, POST);
  1262. doinc(n->right, PRE);
  1263. sugen(n->right, result, nn, w);
  1264. break;
  1265. }
  1266. return;
  1267. copy:
  1268. if(result == D_NONE)
  1269. return;
  1270. rg = regaddr(D_NONE);
  1271. lcgen(n, rg, Z);
  1272. lg = regaddr(D_NONE);
  1273. if(result == D_TOS) {
  1274. adjsp(s - argoff + w);
  1275. gopcode(OADDR, types[TIND], result, nn, lg, n);
  1276. } else
  1277. if(result == D_TREE) {
  1278. if(nn->complex >= FNX) {
  1279. gopcode(OAS, types[TIND], rg, n, D_TOS, n);
  1280. s = argoff;
  1281. lcgen(nn, lg, Z);
  1282. adjsp(s - argoff);
  1283. gopcode(OAS, types[TIND], D_TOS, n, rg, n);
  1284. } else
  1285. lcgen(nn, lg, Z);
  1286. } else
  1287. diag(n, "unknown su result: %R", result);
  1288. if(w % SZ_LONG)
  1289. diag(Z, "sucopy width not 0%%%d", SZ_LONG);
  1290. v = w / SZ_LONG;
  1291. if(v & 1) {
  1292. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1293. v--;
  1294. }
  1295. if(v > 6) {
  1296. ng = regalloc(types[TLONG], D_NONE);
  1297. gopcode(OAS, types[TLONG], D_CONST, nodconst(v/2-1), ng, n);
  1298. v = pc;
  1299. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1300. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1301. gbranch(OGT);
  1302. patch(p, v);
  1303. p->from.type = ng;
  1304. p->as = ADBF;
  1305. regfree(ng);
  1306. } else
  1307. while(v > 0) {
  1308. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1309. v--;
  1310. }
  1311. regfree(lg);
  1312. regfree(rg);
  1313. }