blob: ef11e2adb94d231a86d6d4c50251a713e667732e [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include <u.h>
6#include <libc.h>
7#include "gg.h"
8
9/*
10 * attempt to generate 64-bit
11 * res = n
12 * return 1 on success, 0 if op not handled.
13 */
14void
15cgen64(Node *n, Node *res)
16{
17 Node t1, t2, *l, *r;
18 Node lo1, lo2, hi1, hi2;
19 Node al, ah, bl, bh, cl, ch, s, n1, creg;
20 Prog *p1, *p2, *p3, *p4, *p5, *p6;
21
22 uint64 v;
23
24 if(res->op != OINDREG && res->op != ONAME) {
25 dump("n", n);
26 dump("res", res);
27 fatal("cgen64 %O of %O", n->op, res->op);
28 }
29
30 l = n->left;
31 if(!l->addable) {
32 tempname(&t1, l->type);
33 cgen(l, &t1);
34 l = &t1;
35 }
36
37 split64(l, &lo1, &hi1);
38 switch(n->op) {
39 default:
40 fatal("cgen64 %O", n->op);
41
42 case OMINUS:
43 split64(res, &lo2, &hi2);
44
45 regalloc(&t1, lo1.type, N);
46 regalloc(&al, lo1.type, N);
47 regalloc(&ah, hi1.type, N);
48
49 gins(AMOVW, &lo1, &al);
50 gins(AMOVW, &hi1, &ah);
51
52 gmove(ncon(0), &t1);
53 p1 = gins(ASUB, &al, &t1);
54 p1->scond |= C_SBIT;
55 gins(AMOVW, &t1, &lo2);
56
57 gmove(ncon(0), &t1);
58 gins(ASBC, &ah, &t1);
59 gins(AMOVW, &t1, &hi2);
60
61 regfree(&t1);
62 regfree(&al);
63 regfree(&ah);
64 splitclean();
65 splitclean();
66 return;
67
68 case OCOM:
69 regalloc(&t1, lo1.type, N);
70 gmove(ncon(-1), &t1);
71
72 split64(res, &lo2, &hi2);
73 regalloc(&n1, lo1.type, N);
74
75 gins(AMOVW, &lo1, &n1);
76 gins(AEOR, &t1, &n1);
77 gins(AMOVW, &n1, &lo2);
78
79 gins(AMOVW, &hi1, &n1);
80 gins(AEOR, &t1, &n1);
81 gins(AMOVW, &n1, &hi2);
82
83 regfree(&t1);
84 regfree(&n1);
85 splitclean();
86 splitclean();
87 return;
88
89 case OADD:
90 case OSUB:
91 case OMUL:
92 case OLSH:
93 case ORSH:
94 case OAND:
95 case OOR:
96 case OXOR:
97 case OLROT:
98 // binary operators.
99 // common setup below.
100 break;
101 }
102
103 // setup for binary operators
104 r = n->right;
105 if(r != N && !r->addable) {
106 tempname(&t2, r->type);
107 cgen(r, &t2);
108 r = &t2;
109 }
110 if(is64(r->type))
111 split64(r, &lo2, &hi2);
112
113 regalloc(&al, lo1.type, N);
114 regalloc(&ah, hi1.type, N);
115
116 // Do op. Leave result in ah:al.
117 switch(n->op) {
118 default:
119 fatal("cgen64: not implemented: %N\n", n);
120
121 case OADD:
122 // TODO: Constants
123 regalloc(&bl, types[TPTR32], N);
124 regalloc(&bh, types[TPTR32], N);
125 gins(AMOVW, &hi1, &ah);
126 gins(AMOVW, &lo1, &al);
127 gins(AMOVW, &hi2, &bh);
128 gins(AMOVW, &lo2, &bl);
129 p1 = gins(AADD, &bl, &al);
130 p1->scond |= C_SBIT;
131 gins(AADC, &bh, &ah);
132 regfree(&bl);
133 regfree(&bh);
134 break;
135
136 case OSUB:
137 // TODO: Constants.
138 regalloc(&bl, types[TPTR32], N);
139 regalloc(&bh, types[TPTR32], N);
140 gins(AMOVW, &lo1, &al);
141 gins(AMOVW, &hi1, &ah);
142 gins(AMOVW, &lo2, &bl);
143 gins(AMOVW, &hi2, &bh);
144 p1 = gins(ASUB, &bl, &al);
145 p1->scond |= C_SBIT;
146 gins(ASBC, &bh, &ah);
147 regfree(&bl);
148 regfree(&bh);
149 break;
150
151 case OMUL:
152 // TODO(kaib): this can be done with 4 regs and does not need 6
153 regalloc(&bl, types[TPTR32], N);
154 regalloc(&bh, types[TPTR32], N);
155 regalloc(&cl, types[TPTR32], N);
156 regalloc(&ch, types[TPTR32], N);
157
158 // load args into bh:bl and bh:bl.
159 gins(AMOVW, &hi1, &bh);
160 gins(AMOVW, &lo1, &bl);
161 gins(AMOVW, &hi2, &ch);
162 gins(AMOVW, &lo2, &cl);
163
164 // bl * cl -> ah al
165 p1 = gins(AMULLU, N, N);
166 p1->from.type = D_REG;
167 p1->from.reg = bl.val.u.reg;
168 p1->reg = cl.val.u.reg;
169 p1->to.type = D_REGREG;
170 p1->to.reg = ah.val.u.reg;
171 p1->to.offset = al.val.u.reg;
172//print("%P\n", p1);
173
174 // bl * ch + ah -> ah
175 p1 = gins(AMULA, N, N);
176 p1->from.type = D_REG;
177 p1->from.reg = bl.val.u.reg;
178 p1->reg = ch.val.u.reg;
179 p1->to.type = D_REGREG2;
180 p1->to.reg = ah.val.u.reg;
181 p1->to.offset = ah.val.u.reg;
182//print("%P\n", p1);
183
184 // bh * cl + ah -> ah
185 p1 = gins(AMULA, N, N);
186 p1->from.type = D_REG;
187 p1->from.reg = bh.val.u.reg;
188 p1->reg = cl.val.u.reg;
189 p1->to.type = D_REGREG2;
190 p1->to.reg = ah.val.u.reg;
191 p1->to.offset = ah.val.u.reg;
192//print("%P\n", p1);
193
194 regfree(&bh);
195 regfree(&bl);
196 regfree(&ch);
197 regfree(&cl);
198
199 break;
200
201 case OLROT:
202 // We only rotate by a constant c in [0,64).
203 // if c >= 32:
204 // lo, hi = hi, lo
205 // c -= 32
206 // if c == 0:
207 // no-op
208 // else:
209 // t = hi
210 // shld hi:lo, c
211 // shld lo:t, c
212 v = mpgetfix(r->val.u.xval);
213 regalloc(&bl, lo1.type, N);
214 regalloc(&bh, hi1.type, N);
215 if(v >= 32) {
216 // reverse during load to do the first 32 bits of rotate
217 v -= 32;
218 gins(AMOVW, &hi1, &bl);
219 gins(AMOVW, &lo1, &bh);
220 } else {
221 gins(AMOVW, &hi1, &bh);
222 gins(AMOVW, &lo1, &bl);
223 }
224 if(v == 0) {
225 gins(AMOVW, &bh, &ah);
226 gins(AMOVW, &bl, &al);
227 } else {
228 // rotate by 1 <= v <= 31
229 // MOVW bl<<v, al
230 // MOVW bh<<v, ah
231 // OR bl>>(32-v), ah
232 // OR bh>>(32-v), al
233 gshift(AMOVW, &bl, SHIFT_LL, v, &al);
234 gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
235 gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
236 gshift(AORR, &bh, SHIFT_LR, 32-v, &al);
237 }
238 regfree(&bl);
239 regfree(&bh);
240 break;
241
242 case OLSH:
243 regalloc(&bl, lo1.type, N);
244 regalloc(&bh, hi1.type, N);
245 gins(AMOVW, &hi1, &bh);
246 gins(AMOVW, &lo1, &bl);
247
248 if(r->op == OLITERAL) {
249 v = mpgetfix(r->val.u.xval);
250 if(v >= 64) {
251 // TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
252 // here and below (verify it optimizes to EOR)
253 gins(AEOR, &al, &al);
254 gins(AEOR, &ah, &ah);
255 } else
256 if(v > 32) {
257 gins(AEOR, &al, &al);
258 // MOVW bl<<(v-32), ah
259 gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
260 } else
261 if(v == 32) {
262 gins(AEOR, &al, &al);
263 gins(AMOVW, &bl, &ah);
264 } else
265 if(v > 0) {
266 // MOVW bl<<v, al
267 gshift(AMOVW, &bl, SHIFT_LL, v, &al);
268
269 // MOVW bh<<v, ah
270 gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
271
272 // OR bl>>(32-v), ah
273 gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
274 } else {
275 gins(AMOVW, &bl, &al);
276 gins(AMOVW, &bh, &ah);
277 }
278 goto olsh_break;
279 }
280
281 regalloc(&s, types[TUINT32], N);
282 regalloc(&creg, types[TUINT32], N);
283 if (is64(r->type)) {
284 // shift is >= 1<<32
285 split64(r, &cl, &ch);
286 gmove(&ch, &s);
287 gins(ATST, &s, N);
288 p6 = gbranch(ABNE, T, 0);
289 gmove(&cl, &s);
290 splitclean();
291 } else {
292 gmove(r, &s);
293 p6 = P;
294 }
295 gins(ATST, &s, N);
296
297 // shift == 0
298 p1 = gins(AMOVW, &bl, &al);
299 p1->scond = C_SCOND_EQ;
300 p1 = gins(AMOVW, &bh, &ah);
301 p1->scond = C_SCOND_EQ;
302 p2 = gbranch(ABEQ, T, 0);
303
304 // shift is < 32
305 nodconst(&n1, types[TUINT32], 32);
306 gmove(&n1, &creg);
307 gcmp(ACMP, &s, &creg);
308
309 // MOVW.LO bl<<s, al
310 p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
311 p1->scond = C_SCOND_LO;
312
313 // MOVW.LO bh<<s, ah
314 p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
315 p1->scond = C_SCOND_LO;
316
317 // SUB.LO s, creg
318 p1 = gins(ASUB, &s, &creg);
319 p1->scond = C_SCOND_LO;
320
321 // OR.LO bl>>creg, ah
322 p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
323 p1->scond = C_SCOND_LO;
324
325 // BLO end
326 p3 = gbranch(ABLO, T, 0);
327
328 // shift == 32
329 p1 = gins(AEOR, &al, &al);
330 p1->scond = C_SCOND_EQ;
331 p1 = gins(AMOVW, &bl, &ah);
332 p1->scond = C_SCOND_EQ;
333 p4 = gbranch(ABEQ, T, 0);
334
335 // shift is < 64
336 nodconst(&n1, types[TUINT32], 64);
337 gmove(&n1, &creg);
338 gcmp(ACMP, &s, &creg);
339
340 // EOR.LO al, al
341 p1 = gins(AEOR, &al, &al);
342 p1->scond = C_SCOND_LO;
343
344 // MOVW.LO creg>>1, creg
345 p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
346 p1->scond = C_SCOND_LO;
347
348 // SUB.LO creg, s
349 p1 = gins(ASUB, &creg, &s);
350 p1->scond = C_SCOND_LO;
351
352 // MOVW bl<<s, ah
353 p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
354 p1->scond = C_SCOND_LO;
355
356 p5 = gbranch(ABLO, T, 0);
357
358 // shift >= 64
359 if (p6 != P) patch(p6, pc);
360 gins(AEOR, &al, &al);
361 gins(AEOR, &ah, &ah);
362
363 patch(p2, pc);
364 patch(p3, pc);
365 patch(p4, pc);
366 patch(p5, pc);
367 regfree(&s);
368 regfree(&creg);
369
370olsh_break:
371 regfree(&bl);
372 regfree(&bh);
373 break;
374
375
376 case ORSH:
377 regalloc(&bl, lo1.type, N);
378 regalloc(&bh, hi1.type, N);
379 gins(AMOVW, &hi1, &bh);
380 gins(AMOVW, &lo1, &bl);
381
382 if(r->op == OLITERAL) {
383 v = mpgetfix(r->val.u.xval);
384 if(v >= 64) {
385 if(bh.type->etype == TINT32) {
386 // MOVW bh->31, al
387 gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
388
389 // MOVW bh->31, ah
390 gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
391 } else {
392 gins(AEOR, &al, &al);
393 gins(AEOR, &ah, &ah);
394 }
395 } else
396 if(v > 32) {
397 if(bh.type->etype == TINT32) {
398 // MOVW bh->(v-32), al
399 gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
400
401 // MOVW bh->31, ah
402 gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
403 } else {
404 // MOVW bh>>(v-32), al
405 gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
406 gins(AEOR, &ah, &ah);
407 }
408 } else
409 if(v == 32) {
410 gins(AMOVW, &bh, &al);
411 if(bh.type->etype == TINT32) {
412 // MOVW bh->31, ah
413 gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
414 } else {
415 gins(AEOR, &ah, &ah);
416 }
417 } else
418 if( v > 0) {
419 // MOVW bl>>v, al
420 gshift(AMOVW, &bl, SHIFT_LR, v, &al);
421
422 // OR bh<<(32-v), al
423 gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
424
425 if(bh.type->etype == TINT32) {
426 // MOVW bh->v, ah
427 gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
428 } else {
429 // MOVW bh>>v, ah
430 gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
431 }
432 } else {
433 gins(AMOVW, &bl, &al);
434 gins(AMOVW, &bh, &ah);
435 }
436 goto orsh_break;
437 }
438
439 regalloc(&s, types[TUINT32], N);
440 regalloc(&creg, types[TUINT32], N);
441 if(is64(r->type)) {
442 // shift is >= 1<<32
443 split64(r, &cl, &ch);
444 gmove(&ch, &s);
445 gins(ATST, &s, N);
446 if(bh.type->etype == TINT32)
447 p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
448 else
449 p1 = gins(AEOR, &ah, &ah);
450 p1->scond = C_SCOND_NE;
451 p6 = gbranch(ABNE, T, 0);
452 gmove(&cl, &s);
453 splitclean();
454 } else {
455 gmove(r, &s);
456 p6 = P;
457 }
458 gins(ATST, &s, N);
459
460 // shift == 0
461 p1 = gins(AMOVW, &bl, &al);
462 p1->scond = C_SCOND_EQ;
463 p1 = gins(AMOVW, &bh, &ah);
464 p1->scond = C_SCOND_EQ;
465 p2 = gbranch(ABEQ, T, 0);
466
467 // check if shift is < 32
468 nodconst(&n1, types[TUINT32], 32);
469 gmove(&n1, &creg);
470 gcmp(ACMP, &s, &creg);
471
472 // MOVW.LO bl>>s, al
473 p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
474 p1->scond = C_SCOND_LO;
475
476 // SUB.LO s,creg
477 p1 = gins(ASUB, &s, &creg);
478 p1->scond = C_SCOND_LO;
479
480 // OR.LO bh<<(32-s), al
481 p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
482 p1->scond = C_SCOND_LO;
483
484 if(bh.type->etype == TINT32) {
485 // MOVW bh->s, ah
486 p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
487 } else {
488 // MOVW bh>>s, ah
489 p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
490 }
491 p1->scond = C_SCOND_LO;
492
493 // BLO end
494 p3 = gbranch(ABLO, T, 0);
495
496 // shift == 32
497 p1 = gins(AMOVW, &bh, &al);
498 p1->scond = C_SCOND_EQ;
499 if(bh.type->etype == TINT32)
500 gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
501 else
502 gins(AEOR, &ah, &ah);
503 p4 = gbranch(ABEQ, T, 0);
504
505 // check if shift is < 64
506 nodconst(&n1, types[TUINT32], 64);
507 gmove(&n1, &creg);
508 gcmp(ACMP, &s, &creg);
509
510 // MOVW.LO creg>>1, creg
511 p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
512 p1->scond = C_SCOND_LO;
513
514 // SUB.LO creg, s
515 p1 = gins(ASUB, &creg, &s);
516 p1->scond = C_SCOND_LO;
517
518 if(bh.type->etype == TINT32) {
519 // MOVW bh->(s-32), al
520 p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
521 p1->scond = C_SCOND_LO;
522 } else {
523 // MOVW bh>>(v-32), al
524 p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
525 p1->scond = C_SCOND_LO;
526 }
527
528 // BLO end
529 p5 = gbranch(ABLO, T, 0);
530
531 // s >= 64
532 if(p6 != P)
533 patch(p6, pc);
534 if(bh.type->etype == TINT32) {
535 // MOVW bh->31, al
536 gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
537 } else {
538 gins(AEOR, &al, &al);
539 }
540
541 patch(p2, pc);
542 patch(p3, pc);
543 patch(p4, pc);
544 patch(p5, pc);
545 regfree(&s);
546 regfree(&creg);
547
548
549orsh_break:
550 regfree(&bl);
551 regfree(&bh);
552 break;
553
554 case OXOR:
555 case OAND:
556 case OOR:
557 // TODO(kaib): literal optimizations
558 // make constant the right side (it usually is anyway).
559// if(lo1.op == OLITERAL) {
560// nswap(&lo1, &lo2);
561// nswap(&hi1, &hi2);
562// }
563// if(lo2.op == OLITERAL) {
564// // special cases for constants.
565// lv = mpgetfix(lo2.val.u.xval);
566// hv = mpgetfix(hi2.val.u.xval);
567// splitclean(); // right side
568// split64(res, &lo2, &hi2);
569// switch(n->op) {
570// case OXOR:
571// gmove(&lo1, &lo2);
572// gmove(&hi1, &hi2);
573// switch(lv) {
574// case 0:
575// break;
576// case 0xffffffffu:
577// gins(ANOTL, N, &lo2);
578// break;
579// default:
580// gins(AXORL, ncon(lv), &lo2);
581// break;
582// }
583// switch(hv) {
584// case 0:
585// break;
586// case 0xffffffffu:
587// gins(ANOTL, N, &hi2);
588// break;
589// default:
590// gins(AXORL, ncon(hv), &hi2);
591// break;
592// }
593// break;
594
595// case OAND:
596// switch(lv) {
597// case 0:
598// gins(AMOVL, ncon(0), &lo2);
599// break;
600// default:
601// gmove(&lo1, &lo2);
602// if(lv != 0xffffffffu)
603// gins(AANDL, ncon(lv), &lo2);
604// break;
605// }
606// switch(hv) {
607// case 0:
608// gins(AMOVL, ncon(0), &hi2);
609// break;
610// default:
611// gmove(&hi1, &hi2);
612// if(hv != 0xffffffffu)
613// gins(AANDL, ncon(hv), &hi2);
614// break;
615// }
616// break;
617
618// case OOR:
619// switch(lv) {
620// case 0:
621// gmove(&lo1, &lo2);
622// break;
623// case 0xffffffffu:
624// gins(AMOVL, ncon(0xffffffffu), &lo2);
625// break;
626// default:
627// gmove(&lo1, &lo2);
628// gins(AORL, ncon(lv), &lo2);
629// break;
630// }
631// switch(hv) {
632// case 0:
633// gmove(&hi1, &hi2);
634// break;
635// case 0xffffffffu:
636// gins(AMOVL, ncon(0xffffffffu), &hi2);
637// break;
638// default:
639// gmove(&hi1, &hi2);
640// gins(AORL, ncon(hv), &hi2);
641// break;
642// }
643// break;
644// }
645// splitclean();
646// splitclean();
647// goto out;
648// }
649 regalloc(&n1, lo1.type, N);
650 gins(AMOVW, &lo1, &al);
651 gins(AMOVW, &hi1, &ah);
652 gins(AMOVW, &lo2, &n1);
653 gins(optoas(n->op, lo1.type), &n1, &al);
654 gins(AMOVW, &hi2, &n1);
655 gins(optoas(n->op, lo1.type), &n1, &ah);
656 regfree(&n1);
657 break;
658 }
659 if(is64(r->type))
660 splitclean();
661 splitclean();
662
663 split64(res, &lo1, &hi1);
664 gins(AMOVW, &al, &lo1);
665 gins(AMOVW, &ah, &hi1);
666 splitclean();
667
668//out:
669 regfree(&al);
670 regfree(&ah);
671}
672
673/*
674 * generate comparison of nl, nr, both 64-bit.
675 * nl is memory; nr is constant or memory.
676 */
677void
678cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
679{
680 Node lo1, hi1, lo2, hi2, r1, r2;
681 Prog *br;
682 Type *t;
683
684 split64(nl, &lo1, &hi1);
685 split64(nr, &lo2, &hi2);
686
687 // compare most significant word;
688 // if they differ, we're done.
689 t = hi1.type;
690 regalloc(&r1, types[TINT32], N);
691 regalloc(&r2, types[TINT32], N);
692 gins(AMOVW, &hi1, &r1);
693 gins(AMOVW, &hi2, &r2);
694 gcmp(ACMP, &r1, &r2);
695 regfree(&r1);
696 regfree(&r2);
697
698 br = P;
699 switch(op) {
700 default:
701 fatal("cmp64 %O %T", op, t);
702 case OEQ:
703 // cmp hi
704 // bne L
705 // cmp lo
706 // beq to
707 // L:
708 br = gbranch(ABNE, T, -likely);
709 break;
710 case ONE:
711 // cmp hi
712 // bne to
713 // cmp lo
714 // bne to
715 patch(gbranch(ABNE, T, likely), to);
716 break;
717 case OGE:
718 case OGT:
719 // cmp hi
720 // bgt to
721 // blt L
722 // cmp lo
723 // bge to (or bgt to)
724 // L:
725 patch(gbranch(optoas(OGT, t), T, likely), to);
726 br = gbranch(optoas(OLT, t), T, -likely);
727 break;
728 case OLE:
729 case OLT:
730 // cmp hi
731 // blt to
732 // bgt L
733 // cmp lo
734 // ble to (or jlt to)
735 // L:
736 patch(gbranch(optoas(OLT, t), T, likely), to);
737 br = gbranch(optoas(OGT, t), T, -likely);
738 break;
739 }
740
741 // compare least significant word
742 t = lo1.type;
743 regalloc(&r1, types[TINT32], N);
744 regalloc(&r2, types[TINT32], N);
745 gins(AMOVW, &lo1, &r1);
746 gins(AMOVW, &lo2, &r2);
747 gcmp(ACMP, &r1, &r2);
748 regfree(&r1);
749 regfree(&r2);
750
751 // jump again
752 patch(gbranch(optoas(op, t), T, likely), to);
753
754 // point first branch down here if appropriate
755 if(br != P)
756 patch(br, pc);
757
758 splitclean();
759 splitclean();
760}