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
/* ,x/^(print|prtree)\(/i/\/\/ */
4
 
5
void
6
cgen(Node *n, Node *nn)
7
{
8
	Node *l, *r, *t;
9
	Prog *p1;
10
	Node nod, nod1, nod2, nod3, nod4;
11
	int o, hardleft;
12
	long v, curs;
13
	vlong c;
14
 
15
	if(debug['g']) {
16
		prtree(nn, "cgen lhs");
17
		prtree(n, "cgen");
18
	}
19
	if(n == Z || n->type == T)
20
		return;
21
	if(typesuv[n->type->etype]) {
22
		sugen(n, nn, n->type->width);
23
		return;
24
	}
25
	l = n->left;
26
	r = n->right;
27
	o = n->op;
28
// Go's version does the following, but it's the wrong place: doesn't allow assignment
29
//	if(o == OEXREG || nn != Z && nn->op == OEXREG) {
30
//		gmove(n, nn);
31
//		return;
32
//	}
33
 
34
	if(n->addable >= INDEXED) {
35
		if(nn == Z) {
36
			switch(o) {
37
			default:
38
				nullwarn(Z, Z);
39
				break;
40
			case OINDEX:
41
				nullwarn(l, r);
42
				break;
43
			}
44
			return;
45
		}
46
		gmove(n, nn);
47
		return;
48
	}
49
	curs = cursafe;
50
 
51
	if(l->complex >= FNX)
52
	if(r != Z && r->complex >= FNX)
53
	switch(o) {
54
	default:
55
		if(cond(o) && typesuv[l->type->etype])
56
			break;
57
 
58
		regret(&nod, r);
59
		cgen(r, &nod);
60
 
61
		regsalloc(&nod1, r);
62
		gmove(&nod, &nod1);
63
 
64
		regfree(&nod);
65
		nod = *n;
66
		nod.right = &nod1;
67
 
68
		cgen(&nod, nn);
69
		return;
70
 
71
	case OFUNC:
72
	case OCOMMA:
73
	case OANDAND:
74
	case OOROR:
75
	case OCOND:
76
	case ODOT:
77
		break;
78
	}
79
 
80
	hardleft = l->addable < INDEXED || l->complex >= FNX;
81
	switch(o) {
82
	default:
83
		diag(n, "unknown op in cgen: %O", o);
84
		break;
85
 
86
	case ONEG:
87
	case OCOM:
88
		if(nn == Z) {
89
			nullwarn(l, Z);
90
			break;
91
		}
92
		regalloc(&nod, l, nn);
93
		cgen(l, &nod);
94
		gopcode(o, n->type, Z, &nod);
95
		gmove(&nod, nn);
96
		regfree(&nod);
97
		break;
98
 
99
	case OAS:
100
		if(typefd[n->type->etype]) {
101
			cgen(r, &fregnode0);
102
			if(nn != Z)
103
				gins(AFMOVD, &fregnode0, &fregnode0);
104
			if(l->addable < INDEXED) {
105
				reglcgen(&nod, l, Z);
106
				gmove(&fregnode0, &nod);
107
				regfree(&nod);
108
			} else
109
				gmove(&fregnode0, l);
110
			if(nn != Z)
111
				gmove(&fregnode0, nn);
112
			return;
113
		}
114
		if(l->op == OBIT)
115
			goto bitas;
116
		if(!hardleft) {
117
			if(nn != Z || r->addable < INDEXED) {
118
				if(r->complex >= FNX && nn == Z)
119
					regret(&nod, r);
120
				else
121
					regalloc(&nod, r, nn);
122
				cgen(r, &nod);
123
				gmove(&nod, l);
124
				if(nn != Z)
125
					gmove(&nod, nn);
126
				regfree(&nod);
127
			} else
128
				gmove(r, l);
129
			break;
130
		}
131
		if(l->complex >= r->complex) {
132
			if(l->op == OINDEX && r->op == OCONST) {
133
				gmove(r, l);
134
				break;
135
			}
136
			reglcgen(&nod1, l, Z);
137
			if(r->addable >= INDEXED) {
138
				gmove(r, &nod1);
139
				if(nn != Z)
140
					gmove(r, nn);
141
				regfree(&nod1);
142
				break;
143
			}
144
			regalloc(&nod, r, nn);
145
			cgen(r, &nod);
146
		} else {
147
			regalloc(&nod, r, nn);
148
			cgen(r, &nod);
149
			reglcgen(&nod1, l, Z);
150
		}
151
		gmove(&nod, &nod1);
152
		regfree(&nod);
153
		regfree(&nod1);
154
		break;
155
 
156
	bitas:
157
		n = l->left;
158
		regalloc(&nod, r, nn);
159
		if(l->complex >= r->complex) {
160
			reglcgen(&nod1, n, Z);
161
			cgen(r, &nod);
162
		} else {
163
			cgen(r, &nod);
164
			reglcgen(&nod1, n, Z);
165
		}
166
		regalloc(&nod2, n, Z);
167
		gmove(&nod1, &nod2);
168
		bitstore(l, &nod, &nod1, &nod2, nn);
169
		break;
170
 
171
	case OBIT:
172
		if(nn == Z) {
173
			nullwarn(l, Z);
174
			break;
175
		}
176
		bitload(n, &nod, Z, Z, nn);
177
		gmove(&nod, nn);
178
		regfree(&nod);
179
		break;
180
 
181
	case OLSHR:
182
	case OASHL:
183
	case OASHR:
184
		if(nn == Z) {
185
			nullwarn(l, r);
186
			break;
187
		}
188
		if(r->op == OCONST) {
189
			if(r->vconst == 0) {
190
				cgen(l, nn);
191
				break;
192
			}
193
			regalloc(&nod, l, nn);
194
			cgen(l, &nod);
195
			if(o == OASHL && r->vconst == 1)
196
				gopcode(OADD, n->type, &nod, &nod);
197
			else
198
				gopcode(o, n->type, r, &nod);
199
			gmove(&nod, nn);
200
			regfree(&nod);
201
			break;
202
		}
203
 
204
		/*
205
		 * get nod to be D_CX
206
		 */
207
		if(nodreg(&nod, nn, D_CX)) {
208
			regsalloc(&nod1, n);
209
			gmove(&nod, &nod1);
210
			cgen(n, &nod);		/* probably a bug */
211
			gmove(&nod, nn);
212
			gmove(&nod1, &nod);
213
			break;
214
		}
215
		reg[D_CX]++;
216
		if(nn->op == OREGISTER && nn->reg == D_CX)
217
			regalloc(&nod1, l, Z);
218
		else
219
			regalloc(&nod1, l, nn);
220
		if(r->complex >= l->complex) {
221
			cgen(r, &nod);
222
			cgen(l, &nod1);
223
		} else {
224
			cgen(l, &nod1);
225
			cgen(r, &nod);
226
		}
227
		gopcode(o, n->type, &nod, &nod1);
228
		gmove(&nod1, nn);
229
		regfree(&nod);
230
		regfree(&nod1);
231
		break;
232
 
233
	case OADD:
234
	case OSUB:
235
	case OOR:
236
	case OXOR:
237
	case OAND:
238
		if(nn == Z) {
239
			nullwarn(l, r);
240
			break;
241
		}
242
		if(typefd[n->type->etype])
243
			goto fop;
244
		if(r->op == OCONST) {
245
			if(r->vconst == 0 && o != OAND) {
246
				cgen(l, nn);
247
				break;
248
			}
249
		}
250
		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
251
		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
252
			c = l->right->vconst;
253
			if(c > 0 && c <= 3 && nareg(1) >= 4) {
254
				if(l->left->complex >= r->complex) {
255
					regalloc(&nod, l->left, nn);
256
					cgen(l->left, &nod);
257
					if(r->addable < INDEXED) {
258
						regalloc(&nod1, r, Z);
259
						cgen(r, &nod1);
260
						genmuladd(&nod, &nod, 1 << c, &nod1);
261
						regfree(&nod1);
262
					}
263
					else
264
						genmuladd(&nod, &nod, 1 << c, r);
265
				}
266
				else {
267
					regalloc(&nod, r, nn);
268
					cgen(r, &nod);
269
					regalloc(&nod1, l->left, Z);
270
					cgen(l->left, &nod1);
271
					genmuladd(&nod, &nod1, 1 << c, &nod);
272
					regfree(&nod1);
273
				}
274
				gmove(&nod, nn);
275
				regfree(&nod);
276
				break;
277
			}
278
		}
279
		if(r->addable >= INDEXED) {
280
			regalloc(&nod, l, nn);
281
			cgen(l, &nod);
282
			gopcode(o, n->type, r, &nod);
283
			gmove(&nod, nn);
284
			regfree(&nod);
285
			break;
286
		}
287
		if(l->complex >= r->complex) {
288
			regalloc(&nod, l, nn);
289
			cgen(l, &nod);
290
			regalloc(&nod1, r, Z);
291
			cgen(r, &nod1);
292
			gopcode(o, n->type, &nod1, &nod);
293
		} else {
294
			regalloc(&nod1, r, nn);
295
			cgen(r, &nod1);
296
			regalloc(&nod, l, Z);
297
			cgen(l, &nod);
298
			gopcode(o, n->type, &nod1, &nod);
299
		}
300
		gmove(&nod, nn);
301
		regfree(&nod);
302
		regfree(&nod1);
303
		break;
304
 
305
	case OLMOD:
306
	case OMOD:
307
	case OLMUL:
308
	case OLDIV:
309
	case OMUL:
310
	case ODIV:
311
		if(nn == Z) {
312
			nullwarn(l, r);
313
			break;
314
		}
315
		if(typefd[n->type->etype])
316
			goto fop;
317
		if(r->op == OCONST) {
318
			SET(v);
319
			switch(o) {
320
			case ODIV:
321
			case OMOD:
322
				c = r->vconst;
323
				if(c < 0)
324
					c = -c;
325
				v = log2(c);
326
				if(v < 0)
327
					break;
328
				/* fall thru */
329
			case OMUL:
330
			case OLMUL:
331
				regalloc(&nod, l, nn);
332
				cgen(l, &nod);
333
				switch(o) {
334
				case OMUL:
335
				case OLMUL:
336
					mulgen(n->type, r, &nod);
337
					break;
338
				case ODIV:
339
					sdiv2(r->vconst, v, l, &nod);
340
					break;
341
				case OMOD:
342
					smod2(r->vconst, v, l, &nod);
343
					break;
344
				}
345
				gmove(&nod, nn);
346
				regfree(&nod);
347
				goto done;
348
			case OLDIV:
349
				c = r->vconst;
350
				if((c & 0x80000000) == 0)
351
					break;
352
				regalloc(&nod1, l, Z);
353
				cgen(l, &nod1);
354
				regalloc(&nod, l, nn);
355
				zeroregm(&nod);
356
				gins(ACMPL, &nod1, nodconst(c));
357
				gins(ASBBL, nodconst(-1), &nod);
358
				regfree(&nod1);
359
				gmove(&nod, nn);
360
				regfree(&nod);
361
				goto done;
362
			}
363
		}
364
 
365
		if(o == OMUL) {
366
			if(l->addable >= INDEXED) {
367
				t = l;
368
				l = r;
369
				r = t;
370
				goto imula;
371
			}
372
			else if(r->addable >= INDEXED) {
373
			imula:
374
/* should favour AX */
375
				regalloc(&nod, l, nn);
376
				cgen(l, &nod);
377
				gopcode(OMUL, n->type, r, &nod);
378
			}
379
			else {
380
/* should favour AX */
381
				regalloc(&nod, l, nn);
382
				cgen(l, &nod);
383
				regalloc(&nod1, r, Z);
384
				cgen(r, &nod1);
385
				gopcode(OMUL, n->type, &nod1, &nod);
386
				regfree(&nod1);
387
			}
388
			gmove(&nod, nn);
389
			regfree(&nod);
390
			goto done;
391
		}
392
 
393
		/*
394
		 * get nod to be D_AX
395
		 * get nod1 to be D_DX
396
		 */
397
		if(nodreg(&nod, nn, D_AX)) {
398
			regsalloc(&nod2, n);
399
			gmove(&nod, &nod2);
400
			v = reg[D_AX];
401
			reg[D_AX] = 0;
402
 
403
			if(isreg(l, D_AX)) {
404
				nod3 = *n;
405
				nod3.left = &nod2;
406
				cgen(&nod3, nn);
407
			} else
408
			if(isreg(r, D_AX)) {
409
				nod3 = *n;
410
				nod3.right = &nod2;
411
				cgen(&nod3, nn);
412
			} else
413
				cgen(n, nn);
414
 
415
			gmove(&nod2, &nod);
416
			reg[D_AX] = v;
417
			break;
418
		}
419
		if(nodreg(&nod1, nn, D_DX)) {
420
			regsalloc(&nod2, n);
421
			gmove(&nod1, &nod2);
422
			v = reg[D_DX];
423
			reg[D_DX] = 0;
424
 
425
			if(isreg(l, D_DX)) {
426
				nod3 = *n;
427
				nod3.left = &nod2;
428
				cgen(&nod3, nn);
429
			} else
430
			if(isreg(r, D_DX)) {
431
				nod3 = *n;
432
				nod3.right = &nod2;
433
				cgen(&nod3, nn);
434
			} else
435
				cgen(n, nn);
436
 
437
			gmove(&nod2, &nod1);
438
			reg[D_DX] = v;
439
			break;
440
		}
441
		reg[D_AX]++;
442
 
443
		if(r->op == OCONST) {
444
			switch(o) {
445
			case ODIV:
446
				reg[D_DX]++;
447
				if(l->addable < INDEXED) {
448
					regalloc(&nod2, l, Z);
449
					cgen(l, &nod2);
450
					l = &nod2;
451
				}
452
				sdivgen(l, r, &nod, &nod1);
453
				gmove(&nod1, nn);
454
				if(l == &nod2)
455
					regfree(l);
456
				goto freeaxdx;
457
			case OLDIV:
458
				reg[D_DX]++;
459
				if(l->addable < INDEXED) {
460
					regalloc(&nod2, l, Z);
461
					cgen(l, &nod2);
462
					l = &nod2;
463
				}
464
				udivgen(l, r, &nod, &nod1);
465
				gmove(&nod1, nn);
466
				if(l == &nod2)
467
					regfree(l);
468
				goto freeaxdx;
469
			}
470
		}
471
 
472
		if(l->complex >= r->complex) {
473
			cgen(l, &nod);
474
			reg[D_DX]++;
475
			if(o == ODIV || o == OMOD)
476
				gins(ACDQ, Z, Z);
477
			if(o == OLDIV || o == OLMOD)
478
				zeroregm(&nod1);
479
			if(r->addable < INDEXED || r->op == OCONST) {
480
				regsalloc(&nod3, r);
481
				cgen(r, &nod3);
482
				gopcode(o, n->type, &nod3, Z);
483
			} else
484
				gopcode(o, n->type, r, Z);
485
		} else {
486
			regsalloc(&nod3, r);
487
			cgen(r, &nod3);
488
			cgen(l, &nod);
489
			reg[D_DX]++;
490
			if(o == ODIV || o == OMOD)
491
				gins(ACDQ, Z, Z);
492
			if(o == OLDIV || o == OLMOD)
493
				zeroregm(&nod1);
494
			gopcode(o, n->type, &nod3, Z);
495
		}
496
		if(o == OMOD || o == OLMOD)
497
			gmove(&nod1, nn);
498
		else
499
			gmove(&nod, nn);
500
	freeaxdx:
501
		regfree(&nod);
502
		regfree(&nod1);
503
		break;
504
 
505
	case OASLSHR:
506
	case OASASHL:
507
	case OASASHR:
508
		if(r->op == OCONST)
509
			goto asand;
510
		if(l->op == OBIT)
511
			goto asbitop;
512
		if(typefd[n->type->etype])
513
			goto asfop;
514
 
515
		/*
516
		 * get nod to be D_CX
517
		 */
518
		if(nodreg(&nod, nn, D_CX)) {
519
			regsalloc(&nod1, n);
520
			gmove(&nod, &nod1);
521
			cgen(n, &nod);
522
			if(nn != Z)
523
				gmove(&nod, nn);
524
			gmove(&nod1, &nod);
525
			break;
526
		}
527
		reg[D_CX]++;
528
 
529
		if(r->complex >= l->complex) {
530
			cgen(r, &nod);
531
			if(hardleft)
532
				reglcgen(&nod1, l, Z);
533
			else
534
				nod1 = *l;
535
		} else {
536
			if(hardleft)
537
				reglcgen(&nod1, l, Z);
538
			else
539
				nod1 = *l;
540
			cgen(r, &nod);
541
		}
542
 
543
		gopcode(o, l->type, &nod, &nod1);
544
		regfree(&nod);
545
		if(nn != Z)
546
			gmove(&nod1, nn);
547
		if(hardleft)
548
			regfree(&nod1);
549
		break;
550
 
551
	case OASAND:
552
	case OASADD:
553
	case OASSUB:
554
	case OASXOR:
555
	case OASOR:
556
	asand:
557
		if(l->op == OBIT)
558
			goto asbitop;
559
		if(typefd[n->type->etype]||typefd[r->type->etype])
560
			goto asfop;
561
		if(l->complex >= r->complex) {
562
			if(hardleft)
563
				reglcgen(&nod, l, Z);
564
			else
565
				nod = *l;
566
			if(r->op != OCONST) {
567
				regalloc(&nod1, r, nn);
568
				cgen(r, &nod1);
569
				gopcode(o, l->type, &nod1, &nod);
570
				regfree(&nod1);
571
			} else
572
				gopcode(o, l->type, r, &nod);
573
		} else {
574
			regalloc(&nod1, r, nn);
575
			cgen(r, &nod1);
576
			if(hardleft)
577
				reglcgen(&nod, l, Z);
578
			else
579
				nod = *l;
580
			gopcode(o, l->type, &nod1, &nod);
581
			regfree(&nod1);
582
		}
583
		if(nn != Z)
584
			gmove(&nod, nn);
585
		if(hardleft)
586
			regfree(&nod);
587
		break;
588
 
589
	case OASLMUL:
590
	case OASLDIV:
591
	case OASLMOD:
592
	case OASMUL:
593
	case OASDIV:
594
	case OASMOD:
595
		if(l->op == OBIT)
596
			goto asbitop;
597
		if(typefd[n->type->etype]||typefd[r->type->etype])
598
			goto asfop;
599
		if(r->op == OCONST) {
600
			SET(v);
601
			switch(o) {
602
			case OASDIV:
603
			case OASMOD:
604
				c = r->vconst;
605
				if(c < 0)
606
					c = -c;
607
				v = log2(c);
608
				if(v < 0)
609
					break;
610
				/* fall thru */
611
			case OASMUL:
612
			case OASLMUL:
613
				if(hardleft)
614
					reglcgen(&nod2, l, Z);
615
				else
616
					nod2 = *l;
617
				regalloc(&nod, l, nn);
618
				cgen(&nod2, &nod);
619
				switch(o) {
620
				case OASMUL:
621
				case OASLMUL:
622
					mulgen(n->type, r, &nod);
623
					break;
624
				case OASDIV:
625
					sdiv2(r->vconst, v, l, &nod);
626
					break;
627
				case OASMOD:
628
					smod2(r->vconst, v, l, &nod);
629
					break;
630
				}
631
			havev:
632
				gmove(&nod, &nod2);
633
				if(nn != Z)
634
					gmove(&nod, nn);
635
				if(hardleft)
636
					regfree(&nod2);
637
				regfree(&nod);
638
				goto done;
639
			case OASLDIV:
640
				c = r->vconst;
641
				if((c & 0x80000000) == 0)
642
					break;
643
				if(hardleft)
644
					reglcgen(&nod2, l, Z);
645
				else
646
					nod2 = *l;
647
				regalloc(&nod1, l, nn);
648
				cgen(&nod2, &nod1);
649
				regalloc(&nod, l, nn);
650
				zeroregm(&nod);
651
				gins(ACMPL, &nod1, nodconst(c));
652
				gins(ASBBL, nodconst(-1), &nod);
653
				regfree(&nod1);
654
				goto havev;
655
			}
656
		}
657
 
658
		if(o == OASMUL) {
659
/* should favour AX */
660
			regalloc(&nod, l, nn);
661
			if(r->complex >= FNX) {
662
				regalloc(&nod1, r, Z);
663
				cgen(r, &nod1);
664
				r = &nod1;
665
			}
666
			if(hardleft)
667
				reglcgen(&nod2, l, Z);
668
			else
669
				nod2 = *l;
670
			cgen(&nod2, &nod);
671
			if(r->addable < INDEXED) {
672
				if(r->complex < FNX) {
673
					regalloc(&nod1, r, Z);
674
					cgen(r, &nod1);
675
				}
676
				gopcode(OASMUL, n->type, &nod1, &nod);
677
				regfree(&nod1);
678
			}
679
			else
680
				gopcode(OASMUL, n->type, r, &nod);
681
			if(r == &nod1)
682
				regfree(r);
683
			gmove(&nod, &nod2);
684
			if(nn != Z)
685
				gmove(&nod, nn);
686
			regfree(&nod);
687
			if(hardleft)
688
				regfree(&nod2);
689
			goto done;
690
		}
691
 
692
		/*
693
		 * get nod to be D_AX
694
		 * get nod1 to be D_DX
695
		 */
696
		if(nodreg(&nod, nn, D_AX)) {
697
			regsalloc(&nod2, n);
698
			gmove(&nod, &nod2);
699
			v = reg[D_AX];
700
			reg[D_AX] = 0;
701
 
702
			if(isreg(l, D_AX)) {
703
				nod3 = *n;
704
				nod3.left = &nod2;
705
				cgen(&nod3, nn);
706
			} else
707
			if(isreg(r, D_AX)) {
708
				nod3 = *n;
709
				nod3.right = &nod2;
710
				cgen(&nod3, nn);
711
			} else
712
				cgen(n, nn);
713
 
714
			gmove(&nod2, &nod);
715
			reg[D_AX] = v;
716
			break;
717
		}
718
		if(nodreg(&nod1, nn, D_DX)) {
719
			regsalloc(&nod2, n);
720
			gmove(&nod1, &nod2);
721
			v = reg[D_DX];
722
			reg[D_DX] = 0;
723
 
724
			if(isreg(l, D_DX)) {
725
				nod3 = *n;
726
				nod3.left = &nod2;
727
				cgen(&nod3, nn);
728
			} else
729
			if(isreg(r, D_DX)) {
730
				nod3 = *n;
731
				nod3.right = &nod2;
732
				cgen(&nod3, nn);
733
			} else
734
				cgen(n, nn);
735
 
736
			gmove(&nod2, &nod1);
737
			reg[D_DX] = v;
738
			break;
739
		}
740
		reg[D_AX]++;
741
		reg[D_DX]++;
742
 
743
		if(l->complex >= r->complex) {
744
			if(hardleft)
745
				reglcgen(&nod2, l, Z);
746
			else
747
				nod2 = *l;
748
			cgen(&nod2, &nod);
749
			if(r->op == OCONST) {
750
				switch(o) {
751
				case OASDIV:
752
					sdivgen(&nod2, r, &nod, &nod1);
753
					goto divdone;
754
				case OASLDIV:
755
					udivgen(&nod2, r, &nod, &nod1);
756
				divdone:
757
					gmove(&nod1, &nod2);
758
					if(nn != Z)
759
						gmove(&nod1, nn);
760
					goto freelxaxdx;
761
				}
762
			}
763
			if(o == OASDIV || o == OASMOD)
764
				gins(ACDQ, Z, Z);
765
			if(o == OASLDIV || o == OASLMOD)
766
				zeroregm(&nod1);
767
			if(r->addable < INDEXED || r->op == OCONST ||
768
			   !typeil[r->type->etype]) {
769
				regalloc(&nod3, r, Z);
770
				cgen(r, &nod3);
771
				gopcode(o, l->type, &nod3, Z);
772
				regfree(&nod3);
773
			} else
774
				gopcode(o, n->type, r, Z);
775
		} else {
776
			regalloc(&nod3, r, Z);
777
			cgen(r, &nod3);
778
			if(hardleft)
779
				reglcgen(&nod2, l, Z);
780
			else
781
				nod2 = *l;
782
			cgen(&nod2, &nod);
783
			if(o == OASDIV || o == OASMOD)
784
				gins(ACDQ, Z, Z);
785
			if(o == OASLDIV || o == OASLMOD)
786
				zeroregm(&nod1);
787
			gopcode(o, l->type, &nod3, Z);
788
			regfree(&nod3);
789
		}
790
		if(o == OASMOD || o == OASLMOD) {
791
			gmove(&nod1, &nod2);
792
			if(nn != Z)
793
				gmove(&nod1, nn);
794
		} else {
795
			gmove(&nod, &nod2);
796
			if(nn != Z)
797
				gmove(&nod, nn);
798
		}
799
	freelxaxdx:
800
		if(hardleft)
801
			regfree(&nod2);
802
		regfree(&nod);
803
		regfree(&nod1);
804
		break;
805
 
806
	fop:
807
		if(l->complex >= r->complex) {
808
			cgen(l, &fregnode0);
809
			if(r->addable < INDEXED) {
810
				cgen(r, &fregnode0);
811
				fgopcode(o, &fregnode0, &fregnode1, 1, 0);
812
			} else
813
				fgopcode(o, r, &fregnode0, 0, 0);
814
		} else {
815
			cgen(r, &fregnode0);
816
			if(l->addable < INDEXED) {
817
				cgen(l, &fregnode0);
818
				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
819
			} else
820
				fgopcode(o, l, &fregnode0, 0, 1);
821
		}
822
		gmove(&fregnode0, nn);
823
		break;
824
 
825
	asfop:
826
		if(l->complex >= r->complex) {
827
			if(hardleft)
828
				reglcgen(&nod, l, Z);
829
			else
830
				nod = *l;
831
			cgen(r, &fregnode0);
832
		} else {
833
			cgen(r, &fregnode0);
834
			if(hardleft)
835
				reglcgen(&nod, l, Z);
836
			else
837
				nod = *l;
838
		}
839
		if(!typefd[l->type->etype]) {
840
			gmove(&nod, &fregnode0);
841
			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
842
		} else
843
			fgopcode(o, &nod, &fregnode0, 0, 1);
844
		if(nn != Z)
845
			gins(AFMOVD, &fregnode0, &fregnode0);
846
		gmove(&fregnode0, &nod);
847
		if(nn != Z)
848
			gmove(&fregnode0, nn);
849
		if(hardleft)
850
			regfree(&nod);
851
		break;
852
 
853
	asbitop:
854
		regalloc(&nod4, n, nn);
855
		if(l->complex >= r->complex) {
856
			bitload(l, &nod, &nod1, &nod2, &nod4);
857
			regalloc(&nod3, r, Z);
858
			cgen(r, &nod3);
859
		} else {
860
			regalloc(&nod3, r, Z);
861
			cgen(r, &nod3);
862
			bitload(l, &nod, &nod1, &nod2, &nod4);
863
		}
864
		gmove(&nod, &nod4);
865
 
866
		if(typefd[nod3.type->etype])
867
			fgopcode(o, &fregnode0, &fregnode1, 1, 1);
868
		else {
869
			Node onod;
870
 
871
			/* incredible grot ... */
872
			onod = nod3;
873
			onod.op = o;
874
			onod.complex = 2;
875
			onod.addable = 0;
876
			onod.type = tfield;
877
			onod.left = &nod4;
878
			onod.right = &nod3;
879
			cgen(&onod, Z);
880
		}
881
		regfree(&nod3);
882
		gmove(&nod4, &nod);
883
		regfree(&nod4);
884
		bitstore(l, &nod, &nod1, &nod2, nn);
885
		break;
886
 
887
	case OADDR:
888
		if(nn == Z) {
889
			nullwarn(l, Z);
890
			break;
891
		}
892
		lcgen(l, nn);
893
		break;
894
 
895
	case OFUNC:
896
		l = uncomma(l);
897
		if(l->complex >= FNX) {
898
			if(l->op != OIND)
899
				diag(n, "bad function call");
900
 
901
			regret(&nod, l->left);
902
			cgen(l->left, &nod);
903
			regsalloc(&nod1, l->left);
904
			gmove(&nod, &nod1);
905
			regfree(&nod);
906
 
907
			nod = *n;
908
			nod.left = &nod2;
909
			nod2 = *l;
910
			nod2.left = &nod1;
911
			nod2.complex = 1;
912
			cgen(&nod, nn);
913
 
914
			return;
915
		}
916
		gargs(r, &nod, &nod1);
917
		if(l->addable < INDEXED) {
918
			reglcgen(&nod, l, nn);
919
			nod.op = OREGISTER;
920
			gopcode(OFUNC, n->type, Z, &nod);
921
			regfree(&nod);
922
		} else
923
			gopcode(OFUNC, n->type, Z, l);
924
		if(REGARG>=0 && reg[REGARG])
925
			reg[REGARG]--;
926
		if(nn != Z) {
927
			regret(&nod, n);
928
			gmove(&nod, nn);
929
			regfree(&nod);
930
		} else
931
		if(typefd[n->type->etype])
932
			gins(AFMOVDP, &fregnode0, &fregnode0);
933
		break;
934
 
935
	case OIND:
936
		if(nn == Z) {
937
			nullwarn(l, Z);
938
			break;
939
		}
940
		regialloc(&nod, n, nn);
941
		r = l;
942
		while(r->op == OADD)
943
			r = r->right;
944
		if(sconst(r)) {
945
			v = r->vconst;
946
			r->vconst = 0;
947
			cgen(l, &nod);
948
			nod.xoffset += v;
949
			r->vconst = v;
950
		} else
951
			cgen(l, &nod);
952
		regind(&nod, n);
953
		gmove(&nod, nn);
954
		regfree(&nod);
955
		break;
956
 
957
	case OEQ:
958
	case ONE:
959
	case OLE:
960
	case OLT:
961
	case OGE:
962
	case OGT:
963
	case OLO:
964
	case OLS:
965
	case OHI:
966
	case OHS:
967
		if(nn == Z) {
968
			nullwarn(l, r);
969
			break;
970
		}
971
		boolgen(n, 1, nn);
972
		break;
973
 
974
	case OANDAND:
975
	case OOROR:
976
		boolgen(n, 1, nn);
977
		if(nn == Z)
978
			patch(p, pc);
979
		break;
980
 
981
	case ONOT:
982
		if(nn == Z) {
983
			nullwarn(l, Z);
984
			break;
985
		}
986
		boolgen(n, 1, nn);
987
		break;
988
 
989
	case OCOMMA:
990
		cgen(l, Z);
991
		cgen(r, nn);
992
		break;
993
 
994
	case OCAST:
995
		if(nn == Z) {
996
			nullwarn(l, Z);
997
			break;
998
		}
999
		/*
1000
		 * convert from types l->n->nn
1001
		 */
1002
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
1003
			/* both null, gen l->nn */
1004
			cgen(l, nn);
1005
			break;
1006
		}
1007
		if(typev[l->type->etype]) {
1008
			cgen64(n, nn);
1009
			break;
1010
		}
1011
		regalloc(&nod, l, nn);
1012
		cgen(l, &nod);
1013
		regalloc(&nod1, n, &nod);
1014
		gmove(&nod, &nod1);
1015
		gmove(&nod1, nn);
1016
		regfree(&nod1);
1017
		regfree(&nod);
1018
		break;
1019
 
1020
	case ODOT:
1021
		sugen(l, nodrat, l->type->width);
1022
		if(nn == Z)
1023
			break;
1024
		warn(n, "non-interruptable temporary");
1025
		nod = *nodrat;
1026
		if(!r || r->op != OCONST) {
1027
			diag(n, "DOT and no offset");
1028
			break;
1029
		}
1030
		nod.xoffset += (long)r->vconst;
1031
		nod.type = n->type;
1032
		cgen(&nod, nn);
1033
		break;
1034
 
1035
	case OCOND:
1036
		bcgen(l, 1);
1037
		p1 = p;
1038
		cgen(r->left, nn);
1039
		gbranch(OGOTO);
1040
		patch(p1, pc);
1041
		p1 = p;
1042
		cgen(r->right, nn);
1043
		patch(p1, pc);
1044
		break;
1045
 
1046
	case OPOSTINC:
1047
	case OPOSTDEC:
1048
		v = 1;
1049
		if(l->type->etype == TIND)
1050
			v = l->type->link->width;
1051
		if(o == OPOSTDEC)
1052
			v = -v;
1053
		if(l->op == OBIT)
1054
			goto bitinc;
1055
		if(nn == Z)
1056
			goto pre;
1057
 
1058
		if(hardleft)
1059
			reglcgen(&nod, l, Z);
1060
		else
1061
			nod = *l;
1062
 
1063
		if(typefd[n->type->etype])
1064
			goto fltinc;
1065
		gmove(&nod, nn);
1066
		gopcode(OADD, n->type, nodconst(v), &nod);
1067
		if(hardleft)
1068
			regfree(&nod);
1069
		break;
1070
 
1071
	case OPREINC:
1072
	case OPREDEC:
1073
		v = 1;
1074
		if(l->type->etype == TIND)
1075
			v = l->type->link->width;
1076
		if(o == OPREDEC)
1077
			v = -v;
1078
		if(l->op == OBIT)
1079
			goto bitinc;
1080
 
1081
	pre:
1082
		if(hardleft)
1083
			reglcgen(&nod, l, Z);
1084
		else
1085
			nod = *l;
1086
		if(typefd[n->type->etype])
1087
			goto fltinc;
1088
		gopcode(OADD, n->type, nodconst(v), &nod);
1089
		if(nn != Z)
1090
			gmove(&nod, nn);
1091
		if(hardleft)
1092
			regfree(&nod);
1093
		break;
1094
 
1095
	fltinc:
1096
		gmove(&nod, &fregnode0);
1097
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
1098
			gins(AFMOVD, &fregnode0, &fregnode0);
1099
		gins(AFLD1, Z, Z);
1100
		if(v < 0)
1101
			fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
1102
		else
1103
			fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
1104
		if(nn != Z && (o == OPREINC || o == OPREDEC))
1105
			gins(AFMOVD, &fregnode0, &fregnode0);
1106
		gmove(&fregnode0, &nod);
1107
		if(hardleft)
1108
			regfree(&nod);
1109
		break;
1110
 
1111
	bitinc:
1112
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
1113
			bitload(l, &nod, &nod1, &nod2, Z);
1114
			gmove(&nod, nn);
1115
			gopcode(OADD, tfield, nodconst(v), &nod);
1116
			bitstore(l, &nod, &nod1, &nod2, Z);
1117
			break;
1118
		}
1119
		bitload(l, &nod, &nod1, &nod2, nn);
1120
		gopcode(OADD, tfield, nodconst(v), &nod);
1121
		bitstore(l, &nod, &nod1, &nod2, nn);
1122
		break;
1123
	}
1124
done:
1125
	cursafe = curs;
1126
}
1127
 
1128
void
1129
reglcgen(Node *t, Node *n, Node *nn)
1130
{
1131
	Node *r;
1132
	long v;
1133
 
1134
	regialloc(t, n, nn);
1135
	if(n->op == OIND) {
1136
		r = n->left;
1137
		while(r->op == OADD)
1138
			r = r->right;
1139
		if(sconst(r)) {
1140
			v = r->vconst;
1141
			r->vconst = 0;
1142
			lcgen(n, t);
1143
			t->xoffset += v;
1144
			r->vconst = v;
1145
			regind(t, n);
1146
			return;
1147
		}
1148
	}
1149
	lcgen(n, t);
1150
	regind(t, n);
1151
}
1152
 
1153
void
1154
lcgen(Node *n, Node *nn)
1155
{
1156
	Prog *p1;
1157
	Node nod;
1158
 
1159
	if(debug['g']) {
1160
		prtree(nn, "lcgen lhs");
1161
		prtree(n, "lcgen");
1162
	}
1163
	if(n == Z || n->type == T)
1164
		return;
1165
	if(nn == Z) {
1166
		nn = &nod;
1167
		regalloc(&nod, n, Z);
1168
	}
1169
	switch(n->op) {
1170
	default:
1171
		if(n->addable < INDEXED) {
1172
			diag(n, "unknown op in lcgen: %O", n->op);
1173
			break;
1174
		}
1175
		gopcode(OADDR, n->type, n, nn);
1176
		break;
1177
 
1178
	case OCOMMA:
1179
		cgen(n->left, n->left);
1180
		lcgen(n->right, nn);
1181
		break;
1182
 
1183
	case OIND:
1184
		cgen(n->left, nn);
1185
		break;
1186
 
1187
	case OCOND:
1188
		bcgen(n->left, 1);
1189
		p1 = p;
1190
		lcgen(n->right->left, nn);
1191
		gbranch(OGOTO);
1192
		patch(p1, pc);
1193
		p1 = p;
1194
		lcgen(n->right->right, nn);
1195
		patch(p1, pc);
1196
		break;
1197
	}
1198
}
1199
 
1200
void
1201
bcgen(Node *n, int true)
1202
{
1203
 
1204
	if(n->type == T)
1205
		gbranch(OGOTO);
1206
	else
1207
		boolgen(n, true, Z);
1208
}
1209
 
1210
void
1211
boolgen(Node *n, int true, Node *nn)
1212
{
1213
	int o;
1214
	Prog *p1, *p2;
1215
	Node *l, *r, nod, nod1;
1216
	long curs;
1217
 
1218
	if(debug['g']) {
1219
		prtree(nn, "boolgen lhs");
1220
		prtree(n, "boolgen");
1221
	}
1222
	curs = cursafe;
1223
	l = n->left;
1224
	r = n->right;
1225
	switch(n->op) {
1226
 
1227
	default:
1228
		if(typev[n->type->etype]) {
1229
			testv(n, true);
1230
			goto com;
1231
		}
1232
		o = ONE;
1233
		if(true)
1234
			o = OEQ;
1235
		if(typefd[n->type->etype]) {
1236
			if(n->addable < INDEXED) {
1237
				cgen(n, &fregnode0);
1238
				gins(AFLDZ, Z, Z);
1239
				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
1240
			} else {
1241
				gins(AFLDZ, Z, Z);
1242
				fgopcode(o, n, &fregnode0, 0, 1);
1243
			}
1244
			goto com;
1245
		}
1246
		/* bad, 13 is address of external that becomes constant */
1247
		if(n->addable >= INDEXED && n->addable != 13) {
1248
			gopcode(o, n->type, n, nodconst(0));
1249
			goto com;
1250
		}
1251
		regalloc(&nod, n, nn);
1252
		cgen(n, &nod);
1253
		gopcode(o, n->type, &nod, nodconst(0));
1254
		regfree(&nod);
1255
		goto com;
1256
 
1257
	case OCONST:
1258
		o = vconst(n);
1259
		if(!true)
1260
			o = !o;
1261
		gbranch(OGOTO);
1262
		if(o) {
1263
			p1 = p;
1264
			gbranch(OGOTO);
1265
			patch(p1, pc);
1266
		}
1267
		goto com;
1268
 
1269
	case OCOMMA:
1270
		cgen(l, Z);
1271
		boolgen(r, true, nn);
1272
		break;
1273
 
1274
	case ONOT:
1275
		boolgen(l, !true, nn);
1276
		break;
1277
 
1278
	case OCOND:
1279
		bcgen(l, 1);
1280
		p1 = p;
1281
		bcgen(r->left, true);
1282
		p2 = p;
1283
		gbranch(OGOTO);
1284
		patch(p1, pc);
1285
		p1 = p;
1286
		bcgen(r->right, !true);
1287
		patch(p2, pc);
1288
		p2 = p;
1289
		gbranch(OGOTO);
1290
		patch(p1, pc);
1291
		patch(p2, pc);
1292
		goto com;
1293
 
1294
	case OANDAND:
1295
		if(!true)
1296
			goto caseor;
1297
 
1298
	caseand:
1299
		bcgen(l, true);
1300
		p1 = p;
1301
		bcgen(r, !true);
1302
		p2 = p;
1303
		patch(p1, pc);
1304
		gbranch(OGOTO);
1305
		patch(p2, pc);
1306
		goto com;
1307
 
1308
	case OOROR:
1309
		if(!true)
1310
			goto caseand;
1311
 
1312
	caseor:
1313
		bcgen(l, !true);
1314
		p1 = p;
1315
		bcgen(r, !true);
1316
		p2 = p;
1317
		gbranch(OGOTO);
1318
		patch(p1, pc);
1319
		patch(p2, pc);
1320
		goto com;
1321
 
1322
	case OEQ:
1323
	case ONE:
1324
	case OLE:
1325
	case OLT:
1326
	case OGE:
1327
	case OGT:
1328
	case OHI:
1329
	case OHS:
1330
	case OLO:
1331
	case OLS:
1332
		o = n->op;
1333
		if(typev[l->type->etype]) {
1334
			if(!true)
1335
				n->op = comrel[relindex(o)];
1336
			cgen64(n, Z);
1337
			goto com;
1338
		}
1339
		if(true)
1340
			o = comrel[relindex(o)];
1341
		if(l->complex >= FNX && r->complex >= FNX) {
1342
			regret(&nod, r);
1343
			cgen(r, &nod);
1344
			regsalloc(&nod1, r);
1345
			gmove(&nod, &nod1);
1346
			regfree(&nod);
1347
			nod = *n;
1348
			nod.right = &nod1;
1349
			boolgen(&nod, true, nn);
1350
			break;
1351
		}
1352
		if(typefd[l->type->etype]) {
1353
			if(l->complex >= r->complex) {
1354
				cgen(l, &fregnode0);
1355
				if(r->addable < INDEXED) {
1356
					cgen(r, &fregnode0);
1357
					o = invrel[relindex(o)];
1358
					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
1359
				} else
1360
					fgopcode(o, r, &fregnode0, 0, 1);
1361
			} else {
1362
				o = invrel[relindex(o)];
1363
				cgen(r, &fregnode0);
1364
				if(l->addable < INDEXED) {
1365
					cgen(l, &fregnode0);
1366
					o = invrel[relindex(o)];
1367
					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
1368
				} else
1369
					fgopcode(o, l, &fregnode0, 0, 1);
1370
			}
1371
			goto com;
1372
		}
1373
		if(l->op == OCONST) {
1374
			o = invrel[relindex(o)];
1375
			/* bad, 13 is address of external that becomes constant */
1376
			if(r->addable < INDEXED || r->addable == 13) {
1377
				regalloc(&nod, r, nn);
1378
				cgen(r, &nod);
1379
				gopcode(o, l->type, &nod, l);
1380
				regfree(&nod);
1381
			} else
1382
				gopcode(o, l->type, r, l);
1383
			goto com;
1384
		}
1385
		if(l->complex >= r->complex) {
1386
			regalloc(&nod, l, nn);
1387
			cgen(l, &nod);
1388
			if(r->addable < INDEXED) {
1389
				regalloc(&nod1, r, Z);
1390
				cgen(r, &nod1);
1391
				gopcode(o, l->type, &nod, &nod1);
1392
				regfree(&nod1);
1393
			} else
1394
				gopcode(o, l->type, &nod, r);
1395
			regfree(&nod);
1396
			goto com;
1397
		}
1398
		regalloc(&nod, r, nn);
1399
		cgen(r, &nod);
1400
		if(l->addable < INDEXED || l->addable == 13) {
1401
			regalloc(&nod1, l, Z);
1402
			cgen(l, &nod1);
1403
			if(typechlp[l->type->etype])
1404
				gopcode(o, types[TINT], &nod1, &nod);
1405
			else
1406
				gopcode(o, l->type, &nod1, &nod);
1407
			regfree(&nod1);
1408
		} else
1409
			gopcode(o, l->type, l, &nod);
1410
		regfree(&nod);
1411
 
1412
	com:
1413
		if(nn != Z) {
1414
			p1 = p;
1415
			gmove(nodconst(1L), nn);
1416
			gbranch(OGOTO);
1417
			p2 = p;
1418
			patch(p1, pc);
1419
			gmove(nodconst(0L), nn);
1420
			patch(p2, pc);
1421
		}
1422
		break;
1423
	}
1424
	cursafe = curs;
1425
}
1426
 
1427
void
1428
sugen(Node *n, Node *nn, long w)
1429
{
1430
	Prog *p1;
1431
	Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r;
1432
	Type *t;
1433
	int c, v, x;
1434
 
1435
	if(n == Z || n->type == T)
1436
		return;
1437
	if(debug['g']) {
1438
		prtree(nn, "sugen lhs");
1439
		prtree(n, "sugen");
1440
	}
1441
	if(nn == nodrat)
1442
		if(w > nrathole)
1443
			nrathole = w;
1444
	switch(n->op) {
1445
	case OIND:
1446
		if(nn == Z) {
1447
			nullwarn(n->left, Z);
1448
			break;
1449
		}
1450
 
1451
	default:
1452
		goto copy;
1453
 
1454
	case OCONST:
1455
		if(n->type && typev[n->type->etype]) {
1456
			if(nn == Z) {
1457
				nullwarn(n->left, Z);
1458
				break;
1459
			}
1460
 
1461
			if(nn->op == OREGPAIR) {
1462
				loadpair(n, nn);
1463
				break;
1464
			}
1465
			else if(!vaddr(nn, 0)) {
1466
				t = nn->type;
1467
				nn->type = types[TLONG];
1468
				reglcgen(&nod1, nn, Z);
1469
				nn->type = t;
1470
 
1471
				gmove(lo64(n), &nod1);
1472
				nod1.xoffset += SZ_LONG;
1473
				gmove(hi64(n), &nod1);
1474
				regfree(&nod1);
1475
			}
1476
			else {
1477
				gins(AMOVL, lo64(n), nn);
1478
				nn->xoffset += SZ_LONG;
1479
				gins(AMOVL, hi64(n), nn);
1480
				nn->xoffset -= SZ_LONG;
1481
				break;
1482
			}
1483
			break;
1484
		}
1485
		goto copy;
1486
 
1487
	case ODOT:
1488
		l = n->left;
1489
		sugen(l, nodrat, l->type->width);
1490
		if(nn == Z)
1491
			break;
1492
		warn(n, "non-interruptable temporary");
1493
		nod1 = *nodrat;
1494
		r = n->right;
1495
		if(!r || r->op != OCONST) {
1496
			diag(n, "DOT and no offset");
1497
			break;
1498
		}
1499
		nod1.xoffset += (long)r->vconst;
1500
		nod1.type = n->type;
1501
		sugen(&nod1, nn, w);
1502
		break;
1503
 
1504
	case OSTRUCT:
1505
		/*
1506
		 * rewrite so lhs has no fn call
1507
		 */
1508
		if(nn != Z && side(nn)) {
1509
			nod1 = *n;
1510
			nod1.type = typ(TIND, n->type);
1511
			regret(&nod2, &nod1);
1512
			lcgen(nn, &nod2);
1513
			regsalloc(&nod0, &nod1);
1514
			cgen(&nod2, &nod0);
1515
			regfree(&nod2);
1516
 
1517
			nod1 = *n;
1518
			nod1.op = OIND;
1519
			nod1.left = &nod0;
1520
			nod1.right = Z;
1521
			nod1.complex = 1;
1522
 
1523
			sugen(n, &nod1, w);
1524
			return;
1525
		}
1526
 
1527
		r = n->left;
1528
		for(t = n->type->link; t != T; t = t->down) {
1529
			l = r;
1530
			if(r->op == OLIST) {
1531
				l = r->left;
1532
				r = r->right;
1533
			}
1534
			if(nn == Z) {
1535
				cgen(l, nn);
1536
				continue;
1537
			}
1538
			/*
1539
			 * hand craft *(&nn + o) = l
1540
			 */
1541
			nod0 = znode;
1542
			nod0.op = OAS;
1543
			nod0.type = t;
1544
			nod0.left = &nod1;
1545
			nod0.right = nil;
1546
 
1547
			nod1 = znode;
1548
			nod1.op = OIND;
1549
			nod1.type = t;
1550
			nod1.left = &nod2;
1551
 
1552
			nod2 = znode;
1553
			nod2.op = OADD;
1554
			nod2.type = typ(TIND, t);
1555
			nod2.left = &nod3;
1556
			nod2.right = &nod4;
1557
 
1558
			nod3 = znode;
1559
			nod3.op = OADDR;
1560
			nod3.type = nod2.type;
1561
			nod3.left = nn;
1562
 
1563
			nod4 = znode;
1564
			nod4.op = OCONST;
1565
			nod4.type = nod2.type;
1566
			nod4.vconst = t->offset;
1567
 
1568
			ccom(&nod0);
1569
			acom(&nod0);
1570
			xcom(&nod0);
1571
			nod0.addable = 0;
1572
			nod0.right = l;
1573
 
1574
			/* prtree(&nod0, "hand craft"); /* */
1575
			cgen(&nod0, Z);
1576
		}
1577
		break;
1578
 
1579
	case OAS:
1580
		if(nn == Z) {
1581
			if(n->addable < INDEXED)
1582
				sugen(n->right, n->left, w);
1583
			break;
1584
		}
1585
 
1586
		sugen(n->right, nodrat, w);
1587
		warn(n, "non-interruptable temporary");
1588
		sugen(nodrat, n->left, w);
1589
		sugen(nodrat, nn, w);
1590
		break;
1591
 
1592
	case OFUNC:
1593
		if(nn == Z) {
1594
			sugen(n, nodrat, w);
1595
			break;
1596
		}
1597
		h = nn;
1598
		if(nn->op == OREGPAIR) {
1599
			regsalloc(&nod1, nn);
1600
			nn = &nod1;
1601
		}
1602
		if(nn->op != OIND) {
1603
			nn = new1(OADDR, nn, Z);
1604
			nn->type = types[TIND];
1605
			nn->addable = 0;
1606
		} else
1607
			nn = nn->left;
1608
		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
1609
		n->type = types[TVOID];
1610
		n->left->type = types[TVOID];
1611
		cgen(n, Z);
1612
		if(h->op == OREGPAIR)
1613
			loadpair(nn->left, h);
1614
		break;
1615
 
1616
	case OCOND:
1617
		bcgen(n->left, 1);
1618
		p1 = p;
1619
		sugen(n->right->left, nn, w);
1620
		gbranch(OGOTO);
1621
		patch(p1, pc);
1622
		p1 = p;
1623
		sugen(n->right->right, nn, w);
1624
		patch(p1, pc);
1625
		break;
1626
 
1627
	case OCOMMA:
1628
		cgen(n->left, Z);
1629
		sugen(n->right, nn, w);
1630
		break;
1631
	}
1632
	return;
1633
 
1634
copy:
1635
	if(nn == Z) {
1636
		switch(n->op) {
1637
		case OASADD:
1638
		case OASSUB:
1639
		case OASAND:
1640
		case OASOR:
1641
		case OASXOR:
1642
 
1643
		case OASMUL:
1644
		case OASLMUL:
1645
 
1646
		case OASASHL:
1647
		case OASASHR:
1648
		case OASLSHR:
1649
			break;
1650
 
1651
		case OPOSTINC:
1652
		case OPOSTDEC:
1653
		case OPREINC:
1654
		case OPREDEC:
1655
			break;
1656
 
1657
		default:
1658
			return;
1659
		}
1660
	}
1661
 
1662
	if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
1663
		t = nn->type;
1664
		nn->type = types[TLONG];
1665
		regialloc(&nod1, nn, Z);
1666
		lcgen(nn, &nod1);
1667
		regsalloc(&nod2, nn);
1668
		nn->type = t;
1669
 
1670
		gins(AMOVL, &nod1, &nod2);
1671
		regfree(&nod1);
1672
 
1673
		nod2.type = typ(TIND, t);
1674
 
1675
		nod1 = nod2;
1676
		nod1.op = OIND;
1677
		nod1.left = &nod2;
1678
		nod1.right = Z;
1679
		nod1.complex = 1;
1680
		nod1.type = t;
1681
 
1682
		sugen(n, &nod1, w);
1683
		return;
1684
	}
1685
 
1686
	x = 0;
1687
	v = w == 8;
1688
	if(v) {
1689
		c = cursafe;
1690
		if(n->left != Z && n->left->complex >= FNX
1691
		&& n->right != Z && n->right->complex >= FNX) {
1692
//			warn(n, "toughie");
1693
			regsalloc(&nod1, n->right);
1694
			cgen(n->right, &nod1);
1695
			nod2 = *n;
1696
			nod2.right = &nod1;
1697
			cgen(&nod2, nn);
1698
			cursafe = c;
1699
			return;
1700
		}
1701
		if(cgen64(n, nn)) {
1702
			cursafe = c;
1703
			return;
1704
		}
1705
		if(n->op == OCOM) {
1706
			n = n->left;
1707
			x = 1;
1708
		}
1709
	}
1710
 
1711
	/* botch, need to save in .safe */
1712
	c = 0;
1713
	if(n->complex > nn->complex) {
1714
		t = n->type;
1715
		n->type = types[TLONG];
1716
		if(v) {
1717
			regalloc(&nod0, n, Z);
1718
			if(!vaddr(n, 0)) {
1719
				reglcgen(&nod1, n, Z);
1720
				n->type = t;
1721
				n = &nod1;
1722
			}
1723
			else
1724
				n->type = t;
1725
		}
1726
		else {
1727
			nodreg(&nod1, n, D_SI);
1728
			if(reg[D_SI]) {
1729
				gins(APUSHL, &nod1, Z);
1730
				c |= 1;
1731
				reg[D_SI]++;
1732
			}
1733
			lcgen(n, &nod1);
1734
			n->type = t;
1735
		}
1736
 
1737
		t = nn->type;
1738
		nn->type = types[TLONG];
1739
		if(v) {
1740
			if(!vaddr(nn, 0)) {
1741
				reglcgen(&nod2, nn, Z);
1742
				nn->type = t;
1743
				nn = &nod2;
1744
			}
1745
			else
1746
				nn->type = t;
1747
		}
1748
		else {
1749
			nodreg(&nod2, nn, D_DI);
1750
			if(reg[D_DI]) {
1751
				gins(APUSHL, &nod2, Z);
1752
				c |= 2;
1753
				reg[D_DI]++;
1754
			}
1755
			lcgen(nn, &nod2);
1756
			nn->type = t;
1757
		}
1758
	} else {
1759
		t = nn->type;
1760
		nn->type = types[TLONG];
1761
		if(v) {
1762
			regalloc(&nod0, nn, Z);
1763
			if(!vaddr(nn, 0)) {
1764
				reglcgen(&nod2, nn, Z);
1765
				nn->type = t;
1766
				nn = &nod2;
1767
			}
1768
			else
1769
				nn->type = t;
1770
		}
1771
		else {
1772
			nodreg(&nod2, nn, D_DI);
1773
			if(reg[D_DI]) {
1774
				gins(APUSHL, &nod2, Z);
1775
				c |= 2;
1776
				reg[D_DI]++;
1777
			}
1778
			lcgen(nn, &nod2);
1779
			nn->type = t;
1780
		}
1781
 
1782
		t = n->type;
1783
		n->type = types[TLONG];
1784
		if(v) {
1785
			if(!vaddr(n, 0)) {
1786
				reglcgen(&nod1, n, Z);
1787
				n->type = t;
1788
				n = &nod1;
1789
			}
1790
			else
1791
				n->type = t;
1792
		}
1793
		else {
1794
			nodreg(&nod1, n, D_SI);
1795
			if(reg[D_SI]) {
1796
				gins(APUSHL, &nod1, Z);
1797
				c |= 1;
1798
				reg[D_SI]++;
1799
			}
1800
			lcgen(n, &nod1);
1801
			n->type = t;
1802
		}
1803
	}
1804
	if(v) {
1805
		gins(AMOVL, n, &nod0);
1806
		if(x)
1807
			gins(ANOTL, Z, &nod0);
1808
		gins(AMOVL, &nod0, nn);
1809
		n->xoffset += SZ_LONG;
1810
		nn->xoffset += SZ_LONG;
1811
		gins(AMOVL, n, &nod0);
1812
		if(x)
1813
			gins(ANOTL, Z, &nod0);
1814
		gins(AMOVL, &nod0, nn);
1815
		n->xoffset -= SZ_LONG;
1816
		nn->xoffset -= SZ_LONG;
1817
		if(nn == &nod2)
1818
			regfree(&nod2);
1819
		if(n == &nod1)
1820
			regfree(&nod1);
1821
		regfree(&nod0);
1822
		return;
1823
	}
1824
	nodreg(&nod3, n, D_CX);
1825
	if(reg[D_CX]) {
1826
		gins(APUSHL, &nod3, Z);
1827
		c |= 4;
1828
		reg[D_CX]++;
1829
	}
1830
	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
1831
	gins(ACLD, Z, Z);
1832
	gins(AREP, Z, Z);
1833
	gins(AMOVSL, Z, Z);
1834
	if(w & (SZ_LONG-1)) {
1835
		/* odd length of packed structure */
1836
		gins(AMOVL, nodconst(w & (SZ_LONG-1)), &nod3);
1837
		gins(AREP, Z, Z);
1838
		gins(AMOVSB, Z, Z);
1839
	}
1840
	if(c & 4) {
1841
		gins(APOPL, Z, &nod3);
1842
		reg[D_CX]--;
1843
	}
1844
	if(c & 2) {
1845
		gins(APOPL, Z, &nod2);
1846
		reg[nod2.reg]--;
1847
	}
1848
	if(c & 1) {
1849
		gins(APOPL, Z, &nod1);
1850
		reg[nod1.reg]--;
1851
	}
1852
}