Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "gc.h"
2
 
3
static void cmpv(Node*, int, Node*);
4
static void testv(Node*, int);
5
static void cgen64(Node*, Node*);
6
static int isvconstable(int, vlong);
7
 
8
void
9
cgen(Node *n, Node *nn)
10
{
11
	Node *l, *r;
12
	Prog *p1;
13
	Node nod, nod1, nod2, nod3, nod4;
14
	int o;
15
	long v, curs;
16
 
17
	if(debug['g']) {
18
		prtree(nn, "cgen lhs");
19
		prtree(n, "cgen");
20
	}
21
	if(n == Z || n->type == T)
22
		return;
23
	if(typesu[n->type->etype]) {
24
		sugen(n, nn, n->type->width);
25
		return;
26
	}
27
	if(typev[n->type->etype]) {
28
		switch(n->op) {
29
		case OCONST:
30
		case OFUNC:
31
			cgen64(n, nn);
32
			return;
33
		}
34
	}
35
	l = n->left;
36
	r = n->right;
37
	o = n->op;
38
	if(n->addable >= INDEXED) {
39
		if(nn == Z) {
40
			switch(o) {
41
			default:
42
				nullwarn(Z, Z);
43
				break;
44
			case OINDEX:
45
				nullwarn(l, r);
46
				break;
47
			}
48
			return;
49
		}
50
		gmove(n, nn);
51
		return;
52
	}
53
	curs = cursafe;
54
 
55
	if(n->complex >= FNX)
56
	if(l->complex >= FNX)
57
	if(r != Z && r->complex >= FNX)
58
	switch(o) {
59
	default:
60
		if(!typev[r->type->etype]) {
61
			regret(&nod, r);
62
			cgen(r, &nod);
63
			regsalloc(&nod1, r);
64
			gmove(&nod, &nod1);
65
			regfree(&nod);
66
		} else {
67
			regsalloc(&nod1, r);
68
			cgen(r, &nod1);
69
		}
70
 
71
		nod = *n;
72
		nod.right = &nod1;
73
		cgen(&nod, nn);
74
		return;
75
 
76
	case OFUNC:
77
	case OCOMMA:
78
	case OANDAND:
79
	case OOROR:
80
	case OCOND:
81
	case ODOT:
82
		break;
83
	}
84
 
85
	switch(o) {
86
	default:
87
		diag(n, "unknown op in cgen: %O", o);
88
		break;
89
 
90
	case ONEG:
91
	case OCOM:
92
		if(nn == Z) {
93
			nullwarn(l, Z);
94
			break;
95
		}
96
		regalloc(&nod, l, nn);
97
		cgen(l, &nod);
98
		gopcode(o, &nod, Z, &nod);
99
		gmove(&nod, nn);
100
		regfree(&nod);
101
		break;
102
 
103
	case OAS:
104
		if(l->op == OBIT)
105
			goto bitas;
106
		if(l->addable >= INDEXED) {
107
			if(nn != Z || r->addable < INDEXED) {
108
				regalloc(&nod, r, nn);
109
				cgen(r, &nod);
110
				gmove(&nod, l);
111
				regfree(&nod);
112
			} else
113
				gmove(r, l);
114
			break;
115
		}
116
		if(l->complex >= r->complex) {
117
			reglcgen(&nod1, l, Z);
118
			if(r->addable >= INDEXED) {
119
				gmove(r, &nod1);
120
				if(nn != Z)
121
					gmove(r, nn);
122
				regfree(&nod1);
123
				break;
124
			}
125
			regalloc(&nod, r, nn);
126
			cgen(r, &nod);
127
		} else {
128
			regalloc(&nod, r, nn);
129
			cgen(r, &nod);
130
			reglcgen(&nod1, l, Z);
131
		}
132
		gmove(&nod, &nod1);
133
		regfree(&nod);
134
		regfree(&nod1);
135
		break;
136
 
137
	bitas:
138
		n = l->left;
139
		regalloc(&nod, r, nn);
140
		if(l->complex >= r->complex) {
141
			reglcgen(&nod1, n, Z);
142
			cgen(r, &nod);
143
		} else {
144
			cgen(r, &nod);
145
			reglcgen(&nod1, n, Z);
146
		}
147
		regalloc(&nod2, n, Z);
148
		gopcode(OAS, &nod1, Z, &nod2);
149
		bitstore(l, &nod, &nod1, &nod2, nn);
150
		break;
151
 
152
	case OBIT:
153
		if(nn == Z) {
154
			nullwarn(l, Z);
155
			break;
156
		}
157
		bitload(n, &nod, Z, Z, nn);
158
		gopcode(OAS, &nod, Z, nn);
159
		regfree(&nod);
160
		break;
161
 
162
	case OXOR:
163
		if(nn != Z)
164
		if(r->op == OCONST && r->vconst == -1){
165
			regalloc(&nod, l, nn);
166
			cgen(l, &nod);
167
			gopcode(OCOM, &nod, Z, &nod);
168
			gmove(&nod, nn);
169
			regfree(&nod);
170
			break;
171
		}
172
 
173
	case OADD:
174
	case OSUB:
175
	case OAND:
176
	case OOR:
177
	case OLSHR:
178
	case OASHL:
179
	case OASHR:
180
		/*
181
		 * immediate operands
182
		 */
183
		if(nn != Z && r->op == OCONST && !typefd[n->type->etype] &&
184
		    (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
185
			regalloc(&nod, l, nn);
186
			cgen(l, &nod);
187
			if(o == OAND || r->vconst != 0)
188
				gopcode(o, r, Z, &nod);
189
			gmove(&nod, nn);
190
			regfree(&nod);
191
			break;
192
		}
193
 
194
	case OMUL:
195
	case OLMUL:
196
	case OLDIV:
197
	case OLMOD:
198
	case ODIV:
199
	case OMOD:
200
		if(nn == Z) {
201
			nullwarn(l, r);
202
			break;
203
		}
204
		if((o == OMUL || o == OLMUL) && !typev[n->type->etype]) {
205
			if(mulcon(n, nn))
206
				break;
207
			if(debug['M'])
208
				print("%L multiply\n", n->lineno);
209
		}
210
		if(l->complex >= r->complex) {
211
			regalloc(&nod, l, nn);
212
			cgen(l, &nod);
213
			if(o != OMUL || typev[n->type->etype] || !sconst(r)) {
214
				regalloc(&nod1, r, Z);
215
				cgen(r, &nod1);
216
				gopcode(o, &nod1, Z, &nod);
217
				regfree(&nod1);
218
			} else
219
				gopcode(o, r, Z, &nod);
220
		} else {
221
			regalloc(&nod1, r, nn);
222
			cgen(r, &nod1);
223
			regalloc(&nod, l, Z);
224
			cgen(l, &nod);
225
			gopcode(o, &nod1, Z, &nod);
226
			regfree(&nod1);
227
		}
228
		gopcode(OAS, &nod, Z, nn);
229
		regfree(&nod);
230
		break;
231
 
232
	case OASLSHR:
233
	case OASASHL:
234
	case OASASHR:
235
	case OASAND:
236
	case OASADD:
237
	case OASSUB:
238
	case OASXOR:
239
	case OASOR:
240
		if(l->op == OBIT)
241
			goto asbitop;
242
		if(r->op == OCONST && !typefd[r->type->etype] && !typefd[n->type->etype] &&
243
		   (!typev[n->type->etype] || isvconstable(o, r->vconst))) {
244
			if(l->addable < INDEXED)
245
				reglcgen(&nod2, l, Z);
246
			else
247
				nod2 = *l;
248
			regalloc(&nod, l, nn);
249
			gopcode(OAS, &nod2, Z, &nod);
250
			gopcode(o, r, Z, &nod);
251
			gopcode(OAS, &nod, Z, &nod2);
252
 
253
			regfree(&nod);
254
			if(l->addable < INDEXED)
255
				regfree(&nod2);
256
			break;
257
		}
258
 
259
	case OASLMUL:
260
	case OASLDIV:
261
	case OASLMOD:
262
	case OASMUL:
263
	case OASDIV:
264
	case OASMOD:
265
		if(l->op == OBIT)
266
			goto asbitop;
267
		if(l->complex >= r->complex) {
268
			if(l->addable < INDEXED)
269
				reglcgen(&nod2, l, Z);
270
			else
271
				nod2 = *l;
272
			regalloc(&nod, r, Z);
273
			cgen(r, &nod);
274
		} else {
275
			regalloc(&nod, r, Z);
276
			cgen(r, &nod);
277
			if(l->addable < INDEXED)
278
				reglcgen(&nod2, l, Z);
279
			else
280
				nod2 = *l;
281
		}
282
		regalloc(&nod1, n, nn);
283
		gopcode(OAS, &nod2, Z, &nod1);
284
		gopcode(o, &nod, Z, &nod1);
285
		gopcode(OAS, &nod1, Z, &nod2);
286
		if(nn != Z)
287
			gopcode(OAS, &nod1, Z, nn);
288
		regfree(&nod);
289
		regfree(&nod1);
290
		if(l->addable < INDEXED)
291
			regfree(&nod2);
292
		break;
293
 
294
	asbitop:
295
		regalloc(&nod4, n, nn);
296
		regalloc(&nod3, r, Z);
297
		if(l->complex >= r->complex) {
298
			bitload(l, &nod, &nod1, &nod2, &nod4);
299
			cgen(r, &nod3);
300
		} else {
301
			cgen(r, &nod3);
302
			bitload(l, &nod, &nod1, &nod2, &nod4);
303
		}
304
		gmove(&nod, &nod4);
305
		gopcode(n->op, &nod3, Z, &nod4);
306
		regfree(&nod3);
307
		gmove(&nod4, &nod);
308
		regfree(&nod4);
309
		bitstore(l, &nod, &nod1, &nod2, nn);
310
		break;
311
 
312
	case OADDR:
313
		if(nn == Z) {
314
			nullwarn(l, Z);
315
			break;
316
		}
317
		lcgen(l, nn);
318
		break;
319
 
320
	case OFUNC:
321
		if(l->complex >= FNX) {
322
			if(l->op != OIND)
323
				diag(n, "bad function call");
324
 
325
			regret(&nod, l->left);
326
			cgen(l->left, &nod);
327
			regsalloc(&nod1, l->left);
328
			gopcode(OAS, &nod, Z, &nod1);
329
			regfree(&nod);
330
 
331
			nod = *n;
332
			nod.left = &nod2;
333
			nod2 = *l;
334
			nod2.left = &nod1;
335
			nod2.complex = 1;
336
			cgen(&nod, nn);
337
 
338
			return;
339
		}
340
		o = reg[REGARG];
341
		gargs(r, &nod, &nod1);
342
		if(l->addable < INDEXED) {
343
			reglcgen(&nod, l, Z);
344
			gopcode(OFUNC, Z, Z, &nod);
345
			regfree(&nod);
346
		} else
347
			gopcode(OFUNC, Z, Z, l);
348
		if(REGARG)
349
			if(o != reg[REGARG])
350
				reg[REGARG]--;
351
		if(nn != Z) {
352
			regret(&nod, n);
353
			gopcode(OAS, &nod, Z, nn);
354
			regfree(&nod);
355
		}
356
		break;
357
 
358
	case OIND:
359
		if(nn == Z) {
360
			cgen(l, nn);
361
			break;
362
		}
363
		regialloc(&nod, n, nn);
364
		r = l;
365
		while(r->op == OADD)
366
			r = r->right;
367
		if(sconst(r)) {
368
			v = r->vconst;
369
			r->vconst = 0;
370
			cgen(l, &nod);
371
			nod.xoffset += v;
372
			r->vconst = v;
373
		} else
374
			cgen(l, &nod);
375
		regind(&nod, n);
376
		gmove(&nod, nn);
377
		regfree(&nod);
378
		break;
379
 
380
	case OEQ:
381
	case ONE:
382
	case OLE:
383
	case OLT:
384
	case OGE:
385
	case OGT:
386
	case OLO:
387
	case OLS:
388
	case OHI:
389
	case OHS:
390
		if(nn == Z) {
391
			nullwarn(l, r);
392
			break;
393
		}
394
		boolgen(n, 1, nn);
395
		break;
396
 
397
	case OANDAND:
398
	case OOROR:
399
		boolgen(n, 1, nn);
400
		if(nn == Z)
401
			patch(p, pc);
402
		break;
403
 
404
	case ONOT:
405
		if(nn == Z) {
406
			nullwarn(l, Z);
407
			break;
408
		}
409
		boolgen(n, 1, nn);
410
		break;
411
 
412
	case OCOMMA:
413
		cgen(l, Z);
414
		cgen(r, nn);
415
		break;
416
 
417
	case OCAST:
418
		if(nn == Z) {
419
			nullwarn(l, Z);
420
			break;
421
		}
422
		/*
423
		 * convert from types l->n->nn
424
		 */
425
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
426
			/* both null, gen l->nn */
427
			cgen(l, nn);
428
			break;
429
		}
430
		if(typev[l->type->etype] || typev[n->type->etype]) {
431
			cgen64(n, nn);
432
			break;
433
		}
434
		regalloc(&nod, l, nn);
435
		cgen(l, &nod);
436
		regalloc(&nod1, n, &nod);
437
		gmove(&nod, &nod1);
438
		gmove(&nod1, nn);
439
		regfree(&nod1);
440
		regfree(&nod);
441
		break;
442
 
443
	case ODOT:
444
		sugen(l, nodrat, l->type->width);
445
		if(nn != Z) {
446
			warn(n, "non-interruptable temporary");
447
			nod = *nodrat;
448
			if(!r || r->op != OCONST) {
449
				diag(n, "DOT and no offset");
450
				break;
451
			}
452
			nod.xoffset += (long)r->vconst;
453
			nod.type = n->type;
454
			cgen(&nod, nn);
455
		}
456
		break;
457
 
458
	case OCOND:
459
		bcgen(l, 1);
460
		p1 = p;
461
		cgen(r->left, nn);
462
		gbranch(OGOTO);
463
		patch(p1, pc);
464
		p1 = p;
465
		cgen(r->right, nn);
466
		patch(p1, pc);
467
		break;
468
 
469
	case OPOSTINC:
470
	case OPOSTDEC:
471
		v = 1;
472
		if(l->type->etype == TIND)
473
			v = l->type->link->width;
474
		if(o == OPOSTDEC)
475
			v = -v;
476
		if(l->op == OBIT)
477
			goto bitinc;
478
		if(nn == Z)
479
			goto pre;
480
 
481
		if(l->addable < INDEXED)
482
			reglcgen(&nod2, l, Z);
483
		else
484
			nod2 = *l;
485
 
486
		regalloc(&nod, l, nn);
487
		gopcode(OAS, &nod2, Z, &nod);
488
		regalloc(&nod1, l, Z);
489
		if(typefd[l->type->etype]) {
490
			regalloc(&nod3, l, Z);
491
			if(v < 0) {
492
				gopcode(OAS, nodfconst(-v), Z, &nod3);
493
				gopcode(OSUB, &nod3, &nod, &nod1);
494
			} else {
495
				gopcode(OAS, nodfconst(v), Z, &nod3);
496
				gopcode(OADD, &nod3, &nod, &nod1);
497
			}
498
			regfree(&nod3);
499
		} else
500
			gopcode(OADD, nodconst(v), &nod, &nod1);
501
		gopcode(OAS, &nod1, Z, &nod2);
502
 
503
		regfree(&nod);
504
		regfree(&nod1);
505
		if(l->addable < INDEXED)
506
			regfree(&nod2);
507
		break;
508
 
509
	case OPREINC:
510
	case OPREDEC:
511
		v = 1;
512
		if(l->type->etype == TIND)
513
			v = l->type->link->width;
514
		if(o == OPREDEC)
515
			v = -v;
516
		if(l->op == OBIT)
517
			goto bitinc;
518
 
519
	pre:
520
		if(l->addable < INDEXED)
521
			reglcgen(&nod2, l, Z);
522
		else
523
			nod2 = *l;
524
 
525
		regalloc(&nod, l, nn);
526
		gopcode(OAS, &nod2, Z, &nod);
527
		if(typefd[l->type->etype]) {
528
			regalloc(&nod3, l, Z);
529
			if(v < 0) {
530
				gopcode(OAS, nodfconst(-v), Z, &nod3);
531
				gopcode(OSUB, &nod3, Z, &nod);
532
			} else {
533
				gopcode(OAS, nodfconst(v), Z, &nod3);
534
				gopcode(OADD, &nod3, Z, &nod);
535
			}
536
			regfree(&nod3);
537
		} else
538
			gopcode(OADD, nodconst(v), Z, &nod);
539
		gopcode(OAS, &nod, Z, &nod2);
540
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
541
			gins(ANOP, l, Z);
542
 
543
		regfree(&nod);
544
		if(l->addable < INDEXED)
545
			regfree(&nod2);
546
		break;
547
 
548
	bitinc:
549
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
550
			bitload(l, &nod, &nod1, &nod2, Z);
551
			gopcode(OAS, &nod, Z, nn);
552
			gopcode(OADD, nodconst(v), Z, &nod);
553
			bitstore(l, &nod, &nod1, &nod2, Z);
554
			break;
555
		}
556
		bitload(l, &nod, &nod1, &nod2, nn);
557
		gopcode(OADD, nodconst(v), Z, &nod);
558
		bitstore(l, &nod, &nod1, &nod2, nn);
559
		break;
560
	}
561
	cursafe = curs;
562
}
563
 
564
void
565
reglcgen(Node *t, Node *n, Node *nn)
566
{
567
	Node *r;
568
	long v;
569
 
570
	regialloc(t, n, nn);
571
	if(n->op == OIND) {
572
		r = n->left;
573
		while(r->op == OADD)
574
			r = r->right;
575
		if(sconst(r)) {
576
			v = r->vconst;
577
			r->vconst = 0;
578
			lcgen(n, t);
579
			t->xoffset += v;
580
			r->vconst = v;
581
			regind(t, n);
582
			return;
583
		}
584
	}
585
	lcgen(n, t);
586
	regind(t, n);
587
}
588
 
589
void
590
lcgen(Node *n, Node *nn)
591
{
592
	Prog *p1;
593
	Node nod;
594
 
595
	if(debug['g']) {
596
		prtree(nn, "lcgen lhs");
597
		prtree(n, "lcgen");
598
	}
599
	if(n == Z || n->type == T)
600
		return;
601
	if(nn == Z) {
602
		nn = &nod;
603
		regalloc(&nod, n, Z);
604
	}
605
	switch(n->op) {
606
	default:
607
		if(n->addable < INDEXED) {
608
			diag(n, "unknown op in lcgen: %O", n->op);
609
			break;
610
		}
611
		nod = *n;
612
		nod.op = OADDR;
613
		nod.left = n;
614
		nod.right = Z;
615
		nod.type = types[TIND];
616
		gopcode(OAS, &nod, Z, nn);
617
		break;
618
 
619
	case OCOMMA:
620
		cgen(n->left, n->left);
621
		lcgen(n->right, nn);
622
		break;
623
 
624
	case OIND:
625
		cgen(n->left, nn);
626
		break;
627
 
628
	case OCOND:
629
		bcgen(n->left, 1);
630
		p1 = p;
631
		lcgen(n->right->left, nn);
632
		gbranch(OGOTO);
633
		patch(p1, pc);
634
		p1 = p;
635
		lcgen(n->right->right, nn);
636
		patch(p1, pc);
637
		break;
638
	}
639
}
640
 
641
void
642
bcgen(Node *n, int true)
643
{
644
 
645
	if(n->type == T)
646
		gbranch(OGOTO);
647
	else
648
		boolgen(n, true, Z);
649
}
650
 
651
void
652
boolgen(Node *n, int true, Node *nn)
653
{
654
	int o, uns;
655
	Prog *p1, *p2;
656
	Node *l, *r, nod, nod1;
657
	long curs;
658
 
659
	if(debug['g']) {
660
		prtree(nn, "boolgen lhs");
661
		prtree(n, "boolgen");
662
	}
663
	uns = 0;
664
	curs = cursafe;
665
	l = n->left;
666
	r = n->right;
667
	switch(n->op) {
668
 
669
	default:
670
		if(n->op == OCONST) {
671
			o = vconst(n);
672
			if(!true)
673
				o = !o;
674
			gbranch(OGOTO);
675
			if(o) {
676
				p1 = p;
677
				gbranch(OGOTO);
678
				patch(p1, pc);
679
			}
680
			goto com;
681
		}
682
		if(typev[n->type->etype]) {
683
			testv(n, true);
684
			goto com;
685
		}
686
		regalloc(&nod, n, nn);
687
		cgen(n, &nod);
688
		o = ONE;
689
		if(true)
690
			o = comrel[relindex(o)];
691
		if(typefd[n->type->etype]) {
692
			nodreg(&nod1, n, NREG+FREGZERO);
693
			gopcode(o, &nod, Z, &nod1);
694
		} else
695
			gopcode(o, &nod, Z, nodconst(0));
696
		regfree(&nod);
697
		goto com;
698
 
699
	case OCOMMA:
700
		cgen(l, Z);
701
		boolgen(r, true, nn);
702
		break;
703
 
704
	case ONOT:
705
		boolgen(l, !true, nn);
706
		break;
707
 
708
	case OCOND:
709
		bcgen(l, 1);
710
		p1 = p;
711
		bcgen(r->left, true);
712
		p2 = p;
713
		gbranch(OGOTO);
714
		patch(p1, pc);
715
		p1 = p;
716
		bcgen(r->right, !true);
717
		patch(p2, pc);
718
		p2 = p;
719
		gbranch(OGOTO);
720
		patch(p1, pc);
721
		patch(p2, pc);
722
		goto com;
723
 
724
	case OANDAND:
725
		if(!true)
726
			goto caseor;
727
 
728
	caseand:
729
		bcgen(l, true);
730
		p1 = p;
731
		bcgen(r, !true);
732
		p2 = p;
733
		patch(p1, pc);
734
		gbranch(OGOTO);
735
		patch(p2, pc);
736
		goto com;
737
 
738
	case OOROR:
739
		if(!true)
740
			goto caseand;
741
 
742
	caseor:
743
		bcgen(l, !true);
744
		p1 = p;
745
		bcgen(r, !true);
746
		p2 = p;
747
		gbranch(OGOTO);
748
		patch(p1, pc);
749
		patch(p2, pc);
750
		goto com;
751
 
752
	case OHI:
753
	case OHS:
754
	case OLO:
755
	case OLS:
756
		uns = 1;
757
		/* fall through */
758
	case OEQ:
759
	case ONE:
760
	case OLE:
761
	case OLT:
762
	case OGE:
763
	case OGT:
764
		if(typev[l->type->etype]){
765
			cmpv(n, true, Z);
766
			goto com;
767
		}
768
		o = n->op;
769
		if(true)
770
			o = comrel[relindex(o)];
771
		if(l->complex >= FNX && r->complex >= FNX) {
772
			regret(&nod, r);
773
			cgen(r, &nod);
774
			regsalloc(&nod1, r);
775
			gopcode(OAS, &nod, Z, &nod1);
776
			regfree(&nod);
777
			nod = *n;
778
			nod.right = &nod1;
779
			boolgen(&nod, true, nn);
780
			break;
781
		}
782
		if(!uns && sconst(r) || (uns || o == OEQ || o == ONE) && uconst(r)) {
783
			regalloc(&nod, l, nn);
784
			cgen(l, &nod);
785
			gopcode(o, &nod, Z, r);
786
			regfree(&nod);
787
			goto com;
788
		}
789
		if(l->complex >= r->complex) {
790
			regalloc(&nod1, l, nn);
791
			cgen(l, &nod1);
792
			regalloc(&nod, r, Z);
793
			cgen(r, &nod);
794
		} else {
795
			regalloc(&nod, r, nn);
796
			cgen(r, &nod);
797
			regalloc(&nod1, l, Z);
798
			cgen(l, &nod1);
799
		}
800
		gopcode(o, &nod1, Z, &nod);
801
		regfree(&nod);
802
		regfree(&nod1);
803
 
804
	com:
805
		if(nn != Z) {
806
			p1 = p;
807
			gopcode(OAS, nodconst(1L), Z, nn);
808
			gbranch(OGOTO);
809
			p2 = p;
810
			patch(p1, pc);
811
			gopcode(OAS, nodconst(0L), Z, nn);
812
			patch(p2, pc);
813
		}
814
		break;
815
	}
816
	cursafe = curs;
817
}
818
 
819
void
820
sugen(Node *n, Node *nn, long w)
821
{
822
	Prog *p1;
823
	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
824
	Type *t;
825
	long pc1;
826
	int i, m, c;
827
 
828
	if(n == Z || n->type == T)
829
		return;
830
	if(nn == nodrat)
831
		if(w > nrathole)
832
			nrathole = w;
833
	if(debug['g']) {
834
		prtree(nn, "sugen lhs");
835
		prtree(n, "sugen");
836
	}
837
	if(typev[n->type->etype]) {
838
		diag(n, "old vlong sugen: %O", n->op);
839
		return;
840
	}
841
	switch(n->op) {
842
	case OIND:
843
		if(nn == Z) {
844
			nullwarn(n->left, Z);
845
			break;
846
		}
847
 
848
	default:
849
		goto copy;
850
 
851
	case ODOT:
852
		l = n->left;
853
		sugen(l, nodrat, l->type->width);
854
		if(nn != Z) {
855
			warn(n, "non-interruptable temporary");
856
			nod1 = *nodrat;
857
			r = n->right;
858
			if(!r || r->op != OCONST) {
859
				diag(n, "DOT and no offset");
860
				break;
861
			}
862
			nod1.xoffset += (long)r->vconst;
863
			nod1.type = n->type;
864
			sugen(&nod1, nn, w);
865
		}
866
		break;
867
 
868
	case OSTRUCT:
869
		/*
870
		 * rewrite so lhs has no side effects
871
		 */
872
		if(nn != Z && side(nn)) {
873
			nod1 = *n;
874
			nod1.type = typ(TIND, n->type);
875
			regalloc(&nod2, &nod1, Z);
876
			lcgen(nn, &nod2);
877
			regsalloc(&nod0, &nod1);
878
			gopcode(OAS, &nod2, Z, &nod0);
879
			regfree(&nod2);
880
 
881
			nod1 = *n;
882
			nod1.op = OIND;
883
			nod1.left = &nod0;
884
			nod1.right = Z;
885
			nod1.complex = 1;
886
 
887
			sugen(n, &nod1, w);
888
			return;
889
		}
890
 
891
		r = n->left;
892
		for(t = n->type->link; t != T; t = t->down) {
893
			l = r;
894
			if(r->op == OLIST) {
895
				l = r->left;
896
				r = r->right;
897
			}
898
			if(nn == Z) {
899
				cgen(l, nn);
900
				continue;
901
			}
902
			/*
903
			 * hand craft *(&nn + o) = l
904
			 */
905
			nod0 = znode;
906
			nod0.op = OAS;
907
			nod0.type = t;
908
			nod0.left = &nod1;
909
			nod0.right = l;
910
 
911
			nod1 = znode;
912
			nod1.op = OIND;
913
			nod1.type = t;
914
			nod1.left = &nod2;
915
 
916
			nod2 = znode;
917
			nod2.op = OADD;
918
			nod2.type = typ(TIND, t);
919
			nod2.left = &nod3;
920
			nod2.right = &nod4;
921
 
922
			nod3 = znode;
923
			nod3.op = OADDR;
924
			nod3.type = nod2.type;
925
			nod3.left = nn;
926
 
927
			nod4 = znode;
928
			nod4.op = OCONST;
929
			nod4.type = nod2.type;
930
			nod4.vconst = t->offset;
931
 
932
			ccom(&nod0);
933
			acom(&nod0);
934
			xcom(&nod0);
935
			nod0.addable = 0;
936
 
937
			/* prtree(&nod0, "hand craft"); /* */
938
			cgen(&nod0, Z);
939
		}
940
		break;
941
 
942
	case OAS:
943
		if(nn == Z) {
944
			if(n->addable < INDEXED)
945
				sugen(n->right, n->left, w);
946
			break;
947
		}
948
		/* BOTCH -- functions can clobber rathole */
949
		sugen(n->right, nodrat, w);
950
		warn(n, "non-interruptable temporary");
951
		sugen(nodrat, n->left, w);
952
		sugen(nodrat, nn, w);
953
		break;
954
 
955
	case OFUNC:
956
		/* this transformation should probably be done earlier */
957
		if(nn == Z) {
958
			sugen(n, nodrat, w);
959
			break;
960
		}
961
		if(nn->op != OIND) {
962
			nn = new1(OADDR, nn, Z);
963
			nn->type = types[TIND];
964
			nn->addable = 0;
965
		} else
966
			nn = nn->left;
967
		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
968
		n->complex = FNX;
969
		n->type = types[TVOID];
970
		n->left->type = types[TVOID];
971
		cgen(n, Z);
972
		break;
973
 
974
	case OCOND:
975
		bcgen(n->left, 1);
976
		p1 = p;
977
		sugen(n->right->left, nn, w);
978
		gbranch(OGOTO);
979
		patch(p1, pc);
980
		p1 = p;
981
		sugen(n->right->right, nn, w);
982
		patch(p1, pc);
983
		break;
984
 
985
	case OCOMMA:
986
		cgen(n->left, Z);
987
		sugen(n->right, nn, w);
988
		break;
989
	}
990
	return;
991
 
992
copy:
993
	if(nn == Z)
994
		return;
995
	if(n->complex >= FNX && nn->complex >= FNX) {
996
		t = nn->type;
997
		nn->type = types[TLONG];
998
		regialloc(&nod1, nn, Z);
999
		lcgen(nn, &nod1);
1000
		regsalloc(&nod2, nn);
1001
		nn->type = t;
1002
 
1003
		gmove(&nod1, &nod2);
1004
		regfree(&nod1);
1005
 
1006
		nod2.type = typ(TIND, t);
1007
 
1008
		nod1 = nod2;
1009
		nod1.op = OIND;
1010
		nod1.left = &nod2;
1011
		nod1.right = Z;
1012
		nod1.complex = 1;
1013
		nod1.type = t;
1014
 
1015
		sugen(n, &nod1, w);
1016
		return;
1017
	}
1018
 
1019
	if(n->complex > nn->complex) {
1020
		t = n->type;
1021
		n->type = types[TLONG];
1022
		reglcgen(&nod1, n, Z);
1023
		n->type = t;
1024
 
1025
		t = nn->type;
1026
		nn->type = types[TLONG];
1027
		reglcgen(&nod2, nn, Z);
1028
		nn->type = t;
1029
	} else {
1030
		t = nn->type;
1031
		nn->type = types[TLONG];
1032
		reglcgen(&nod2, nn, Z);
1033
		nn->type = t;
1034
 
1035
		t = n->type;
1036
		n->type = types[TLONG];
1037
		reglcgen(&nod1, n, Z);
1038
		n->type = t;
1039
	}
1040
 
1041
	w /= SZ_LONG;
1042
	if(w <= 5) {
1043
		layout(&nod1, &nod2, w, 0, Z);
1044
		goto out;
1045
	}
1046
 
1047
	/*
1048
	 * minimize space for unrolling loop
1049
	 * 3,4,5 times. (6 or more is never minimum)
1050
	 * if small structure, try 2 also.
1051
	 */
1052
	c = 0; /* set */
1053
	m = 100;
1054
	i = 3;
1055
	if(w <= 15)
1056
		i = 2;
1057
	for(; i<=5; i++)
1058
		if(i + w%i <= m) {
1059
			c = i;
1060
			m = c + w%c;
1061
		}
1062
 
1063
	regalloc(&nod3, &regnode, Z);
1064
	layout(&nod1, &nod2, w%c, w/c, &nod3);
1065
 
1066
	pc1 = pc;
1067
	layout(&nod1, &nod2, c, 0, Z);
1068
 
1069
	gopcode(OSUB, nodconst(1L), Z, &nod3);
1070
	nod1.op = OREGISTER;
1071
	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
1072
	nod2.op = OREGISTER;
1073
	gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
1074
 
1075
	gopcode(OGT, &nod3, Z, nodconst(0));
1076
	patch(p, pc1);
1077
 
1078
	regfree(&nod3);
1079
out:
1080
	regfree(&nod1);
1081
	regfree(&nod2);
1082
}
1083
 
1084
void
1085
layout(Node *f, Node *t, int c, int cv, Node *cn)
1086
{
1087
	Node t1, t2;
1088
 
1089
	while(c > 3) {
1090
		layout(f, t, 2, 0, Z);
1091
		c -= 2;
1092
	}
1093
 
1094
	regalloc(&t1, &regnode, Z);
1095
	regalloc(&t2, &regnode, Z);
1096
	if(c > 0) {
1097
		gopcode(OAS, f, Z, &t1);
1098
		f->xoffset += SZ_LONG;
1099
	}
1100
	if(cn != Z)
1101
		gopcode(OAS, nodconst(cv), Z, cn);
1102
	if(c > 1) {
1103
		gopcode(OAS, f, Z, &t2);
1104
		f->xoffset += SZ_LONG;
1105
	}
1106
	if(c > 0) {
1107
		gopcode(OAS, &t1, Z, t);
1108
		t->xoffset += SZ_LONG;
1109
	}
1110
	if(c > 2) {
1111
		gopcode(OAS, f, Z, &t1);
1112
		f->xoffset += SZ_LONG;
1113
	}
1114
	if(c > 1) {
1115
		gopcode(OAS, &t2, Z, t);
1116
		t->xoffset += SZ_LONG;
1117
	}
1118
	if(c > 2) {
1119
		gopcode(OAS, &t1, Z, t);
1120
		t->xoffset += SZ_LONG;
1121
	}
1122
	regfree(&t1);
1123
	regfree(&t2);
1124
}
1125
 
1126
/*
1127
 * is the vlong's value directly addressible?
1128
 */
1129
int
1130
isvdirect(Node *n)
1131
{
1132
	return n->op == ONAME || n->op == OCONST || n->op == OINDREG;
1133
}
1134
 
1135
/*
1136
 * can the constant be used with given vlong op?
1137
 */
1138
static int
1139
isvconstable(int o, vlong v)
1140
{
1141
	switch(o) {
1142
	case OADD:
1143
	case OASADD:
1144
		/* there isn't an immediate form for ADDE/SUBE, but there are special ADDME/ADDZE etc */
1145
		return v == 0 || v == -1;
1146
	case OAND:
1147
	case OOR:
1148
	case OXOR:
1149
	case OLSHR:
1150
	case OASHL:
1151
	case OASHR:
1152
	case OASLSHR:
1153
	case OASASHL:
1154
	case OASASHR:
1155
		return 1;
1156
	}
1157
	return 0;
1158
}
1159
 
1160
/*
1161
 * most 64-bit operations: cgen into a register pair, then operate.
1162
 * 64-bit comparisons are handled a little differently because the two underlying
1163
 * comparisons can be compiled separately, since the calculations don't interact.
1164
 */
1165
 
1166
static void
1167
vcgen(Node *n, Node *o, int *f)
1168
{
1169
	*f = 0;
1170
	if(!isvdirect(n)) {
1171
		if(n->complex >= FNX) {
1172
			regsalloc(o, n);
1173
			cgen(n, o);
1174
			return;
1175
		}
1176
		*f = 1;
1177
		if(n->addable < INDEXED && n->op != OIND && n->op != OINDEX) {
1178
			regalloc(o, n, Z);
1179
			cgen(n, o);
1180
		} else
1181
			reglcgen(o, n, Z);
1182
	} else
1183
		*o = *n;
1184
}
1185
 
1186
static int
1187
isuns(int op)
1188
{
1189
	switch(op){
1190
	case OLO:
1191
	case OLS:
1192
	case OHI:
1193
	case OHS:
1194
		return 1;
1195
	default:
1196
		return 0;
1197
	}
1198
}
1199
 
1200
static void
1201
gcmpv(Node *l, Node *r, void (*mov)(Node*, Node*, int), int op)
1202
{
1203
	Node vl, vr;
1204
 
1205
	regalloc(&vl, &regnode, Z);
1206
	mov(l, &vl, 0);
1207
	regalloc(&vr, &regnode, Z);
1208
	mov(r, &vr, 1+isuns(op));
1209
	gopcode(op, &vl, Z, &vr);
1210
	if(vl.op == OREGISTER)
1211
		regfree(&vl);
1212
	if(vr.op == OREGISTER)
1213
		regfree(&vr);
1214
}
1215
 
1216
static void
1217
brcondv(Node *l, Node *r, int chi, int clo)
1218
{
1219
	Prog *p1, *p2, *p3, *p4;
1220
 
1221
	gcmpv(l, r, gloadhi, chi);
1222
	p1 = p;
1223
	gins(ABNE, Z, Z);
1224
	p2 = p;
1225
	gcmpv(l, r, gloadlo, clo);
1226
	p3 = p;
1227
	gbranch(OGOTO);
1228
	p4 = p;
1229
	patch(p1, pc);
1230
	patch(p3, pc);
1231
	gbranch(OGOTO);
1232
	patch(p2, pc);
1233
	patch(p4, pc);
1234
}
1235
 
1236
static void
1237
testv(Node *n, int true)
1238
{
1239
	Node nod;
1240
 
1241
	nod = znode;
1242
	nod.op = ONE;
1243
	nod.left = n;
1244
	nod.right = new1(0, Z, Z);
1245
	*nod.right = *nodconst(0);
1246
	nod.right->type = n->type;
1247
	nod.type = types[TLONG];
1248
	cmpv(&nod, true, Z);
1249
}
1250
 
1251
/*
1252
 * comparison for vlong does high and low order parts separately,
1253
 * which saves loading the latter if the high order comparison suffices
1254
 */
1255
static void
1256
cmpv(Node *n, int true, Node *nn)
1257
{
1258
	Node *l, *r, nod, nod1;
1259
	int o, f1, f2;
1260
	Prog *p1, *p2;
1261
	long curs;
1262
 
1263
	if(debug['g']) {
1264
		if(nn != nil)
1265
			prtree(nn, "cmpv lhs");
1266
		prtree(n, "cmpv");
1267
	}
1268
	curs = cursafe;
1269
	l = n->left;
1270
	r = n->right;
1271
	if(l->complex >= FNX && r->complex >= FNX) {
1272
		regsalloc(&nod1, r);
1273
		cgen(r, &nod1);
1274
		nod = *n;
1275
		nod.right = &nod1;
1276
		cmpv(&nod, true, nn);
1277
		cursafe = curs;
1278
		return;
1279
	}
1280
	if(l->complex >= r->complex) {
1281
		vcgen(l, &nod1, &f1);
1282
		vcgen(r, &nod, &f2);
1283
	} else {
1284
		vcgen(r, &nod, &f2);
1285
		vcgen(l, &nod1, &f1);
1286
	}
1287
	nod.type = types[TLONG];
1288
	nod1.type = types[TLONG];
1289
	o = n->op;
1290
	if(true)
1291
		o = comrel[relindex(o)];
1292
	switch(o){
1293
	case OEQ:
1294
		gcmpv(&nod1, &nod, gloadhi, ONE);
1295
		p1 = p;
1296
		gcmpv(&nod1, &nod, gloadlo, ONE);
1297
		p2 = p;
1298
		gbranch(OGOTO);
1299
		patch(p1, pc);
1300
		patch(p2, pc);
1301
		break;
1302
	case ONE:
1303
		gcmpv(&nod1, &nod, gloadhi, ONE);
1304
		p1 = p;
1305
		gcmpv(&nod1, &nod, gloadlo, OEQ);
1306
		p2 = p;
1307
		patch(p1, pc);
1308
		gbranch(OGOTO);
1309
		patch(p2, pc);
1310
		break;
1311
	case OLE:
1312
		brcondv(&nod1, &nod, OLT, OLS);
1313
		break;
1314
	case OGT:
1315
		brcondv(&nod1, &nod, OGT, OHI);
1316
		break;
1317
	case OLS:
1318
		brcondv(&nod1, &nod, OLO, OLS);
1319
		break;
1320
	case OHI:
1321
		brcondv(&nod1, &nod, OHI, OHI);
1322
		break;
1323
	case OLT:
1324
		brcondv(&nod1, &nod, OLT, OLO);
1325
		break;
1326
	case OGE:
1327
		brcondv(&nod1, &nod, OGT, OHS);
1328
		break;
1329
	case OLO:
1330
		brcondv(&nod1, &nod, OLO, OLO);
1331
		break;
1332
	case OHS:
1333
		brcondv(&nod1, &nod, OHI, OHS);
1334
		break;
1335
	default:
1336
		diag(n, "bad cmpv");
1337
		return;
1338
	}
1339
	if(f1)
1340
		regfree(&nod1);
1341
	if(f2)
1342
		regfree(&nod);
1343
	cursafe = curs;
1344
}
1345
 
1346
static void
1347
cgen64(Node *n, Node *nn)
1348
{
1349
	Node *l, *r, *d;
1350
	Node nod, nod1;
1351
	long curs;
1352
	Type *t;
1353
	int o, m;
1354
 
1355
	curs = cursafe;
1356
	l = n->left;
1357
	r = n->right;
1358
	o = n->op;
1359
	switch(o) {
1360
 
1361
	case OCONST:
1362
		if(nn == Z) {
1363
			nullwarn(n->left, Z);
1364
			break;
1365
		}
1366
		if(nn->op != OREGPAIR) {
1367
//prtree(n, "cgen64 const");
1368
			t = nn->type;
1369
			nn->type = types[TLONG];
1370
			reglcgen(&nod1, nn, Z);
1371
			nn->type = t;
1372
 
1373
			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1374
				gmove(nod32const(n->vconst>>32), &nod1);
1375
			else
1376
				gmove(nod32const(n->vconst), &nod1);
1377
			nod1.xoffset += SZ_LONG;
1378
			if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
1379
				gmove(nod32const(n->vconst), &nod1);
1380
			else
1381
				gmove(nod32const(n->vconst>>32), &nod1);
1382
 
1383
			regfree(&nod1);
1384
		} else
1385
			gmove(n, nn);
1386
		break;
1387
 
1388
	case OCAST:
1389
		/*
1390
		 * convert from types l->n->nn
1391
		 */
1392
		if(typev[l->type->etype]){
1393
			/* vlong to non-vlong */
1394
			if(!isvdirect(l)) {
1395
				if(l->addable < INDEXED && l->op != OIND && l->op != OINDEX) {
1396
					regalloc(&nod, l, l);
1397
					cgen(l, &nod);
1398
					regalloc(&nod1, n, nn);
1399
					gmove(nod.right, &nod1);
1400
				} else {
1401
					reglcgen(&nod, l, Z);
1402
					regalloc(&nod1, n, nn);
1403
					gloadlo(&nod, &nod1, 0);	/* TO DO: not correct for typefd */
1404
				}
1405
				regfree(&nod);
1406
			} else {
1407
				regalloc(&nod1, n, nn);
1408
				gloadlo(l, &nod1, 0);	/* TO DO: not correct for typefd */
1409
			}
1410
		}else{
1411
			/* non-vlong to vlong */
1412
			regalloc(&nod, l, Z);
1413
			cgen(l, &nod);
1414
			regalloc(&nod1, n, nn);
1415
			gmove(&nod, nod1.right);
1416
			if(typeu[l->type->etype])
1417
				gmove(nodconst(0), nod1.left);
1418
			else
1419
				gopcode(OASHR, nodconst(31), nod1.right, nod1.left);
1420
			regfree(&nod);
1421
		}
1422
		gmove(&nod1, nn);
1423
		regfree(&nod1);
1424
		break;
1425
 
1426
	case OFUNC:
1427
		/* this transformation should probably be done earlier */
1428
		if(nn == Z) {
1429
			regsalloc(&nod1, n);
1430
			nn = &nod1;
1431
		}
1432
		m = 0;
1433
		if(nn->op != OIND) {
1434
			if(nn->op == OREGPAIR) {
1435
				m = 1;
1436
				regsalloc(&nod1, nn);
1437
				d = &nod1;
1438
			}else
1439
				d = nn;
1440
			d = new1(OADDR, d, Z);
1441
			d->type = types[TIND];
1442
			d->addable = 0;
1443
		} else
1444
			d = nn->left;
1445
		n = new(OFUNC, l, new(OLIST, d, r));
1446
		n->complex = FNX;
1447
		n->type = types[TVOID];
1448
		n->left->type = types[TVOID];
1449
		cgen(n, Z);
1450
		if(m)
1451
			gmove(&nod1, nn);
1452
		break;
1453
 
1454
	default:
1455
		diag(n, "bad cgen64 %O", o);
1456
		break;
1457
	}
1458
	cursafe = curs;
1459
}