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