Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "gc.h"
2
 
3
void
4
ginit(void)
5
{
6
	int i;
7
	Type *t;
8
 
9
	thechar = 'k';
10
	thestring = "sparc";
11
	exregoffset = REGEXT;
12
	exfregoffset = FREGEXT;
13
	listinit();
14
	nstring = 0;
15
	mnstring = 0;
16
	nrathole = 0;
17
	pc = 0;
18
	breakpc = -1;
19
	continpc = -1;
20
	cases = C;
21
	firstp = P;
22
	lastp = P;
23
	tfield = types[TLONG];
24
 
25
	zprog.link = P;
26
	zprog.as = AGOK;
27
	zprog.reg = NREG;
28
	zprog.from.type = D_NONE;
29
	zprog.from.name = D_NONE;
30
	zprog.from.reg = NREG;
31
	zprog.to = zprog.from;
32
 
33
	regnode.op = OREGISTER;
34
	regnode.class = CEXREG;
35
	regnode.reg = 0;
36
	regnode.complex = 0;
37
	regnode.addable = 11;
38
	regnode.type = types[TLONG];
39
 
40
	constnode.op = OCONST;
41
	constnode.class = CXXX;
42
	constnode.complex = 0;
43
	constnode.addable = 20;
44
	constnode.type = types[TLONG];
45
 
46
	fconstnode.op = OCONST;
47
	fconstnode.class = CXXX;
48
	fconstnode.complex = 0;
49
	fconstnode.addable = 20;
50
	fconstnode.type = types[TDOUBLE];
51
 
52
	nodsafe = new(ONAME, Z, Z);
53
	nodsafe->sym = slookup(".safe");
54
	nodsafe->type = types[TINT];
55
	nodsafe->etype = types[TINT]->etype;
56
	nodsafe->class = CAUTO;
57
	complex(nodsafe);
58
 
59
	t = typ(TARRAY, types[TCHAR]);
60
	symrathole = slookup(".rathole");
61
	symrathole->class = CGLOBL;
62
	symrathole->type = t;
63
 
64
	nodrat = new(ONAME, Z, Z);
65
	nodrat->sym = symrathole;
66
	nodrat->type = types[TIND];
67
	nodrat->etype = TVOID;
68
	nodrat->class = CGLOBL;
69
	complex(nodrat);
70
	nodrat->type = t;
71
 
72
	nodret = new(ONAME, Z, Z);
73
	nodret->sym = slookup(".ret");
74
	nodret->type = types[TIND];
75
	nodret->etype = TIND;
76
	nodret->class = CPARAM;
77
	nodret = new(OIND, nodret, Z);
78
	complex(nodret);
79
 
80
	com64init();
81
 
82
	memset(reg, 0, sizeof(reg));
83
	reg[REGZERO] = 1;
84
	reg[REGLINK] = 1;
85
	reg[REGTMP] = 1;
86
	for(i=NREG; i<NREG+NREG; i+=2)
87
		reg[i+1] = 1;
88
}
89
 
90
void
91
gclean(void)
92
{
93
	int i;
94
	Sym *s;
95
 
96
	for(i=0; i<NREG; i++)
97
		if(i != REGZERO && i != REGTMP && i != REGLINK)
98
		if(reg[i])
99
			diag(Z, "reg %d left allocated", i);
100
	for(i=NREG; i<NREG+NREG; i+=2)
101
		if(reg[i])
102
			diag(Z, "freg %d left allocated", i-NREG);
103
	while(mnstring)
104
		outstring("", 1L);
105
	symstring->type->width = nstring;
106
	symrathole->type->width = nrathole;
107
	for(i=0; i<NHASH; i++)
108
	for(s = hash[i]; s != S; s = s->link) {
109
		if(s->type == T)
110
			continue;
111
		if(s->type->width == 0)
112
			continue;
113
		if(s->class != CGLOBL && s->class != CSTATIC)
114
			continue;
115
		if(s->type == types[TENUM])
116
			continue;
117
		gpseudo(AGLOBL, s, nodconst(s->type->width));
118
	}
119
	nextpc();
120
	p->as = AEND;
121
	outcode();
122
}
123
 
124
void
125
nextpc(void)
126
{
127
 
128
	p = alloc(sizeof(*p));
129
	*p = zprog;
130
	p->lineno = nearln;
131
	pc++;
132
	if(firstp == P) {
133
		firstp = p;
134
		lastp = p;
135
		return;
136
	}
137
	lastp->link = p;
138
	lastp = p;
139
}
140
 
141
void
142
gargs(Node *n, Node *tn1, Node *tn2)
143
{
144
	long regs;
145
	Node fnxargs[20], *fnxp;
146
 
147
	regs = cursafe;
148
 
149
	fnxp = fnxargs;
150
	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
151
 
152
	curarg = 0;
153
	fnxp = fnxargs;
154
	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
155
 
156
	cursafe = regs;
157
}
158
 
159
void
160
garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
161
{
162
	Node nod;
163
 
164
	if(n == Z)
165
		return;
166
	if(n->op == OLIST) {
167
		garg1(n->left, tn1, tn2, f, fnxp);
168
		garg1(n->right, tn1, tn2, f, fnxp);
169
		return;
170
	}
171
	if(f == 0) {
172
		if(n->complex >= FNX) {
173
			regsalloc(*fnxp, n);
174
			nod = znode;
175
			nod.op = OAS;
176
			nod.left = *fnxp;
177
			nod.right = n;
178
			nod.type = n->type;
179
			cgen(&nod, Z);
180
			(*fnxp)++;
181
		}
182
		return;
183
	}
184
	if(typesuv[n->type->etype]) {
185
		regaalloc(tn2, n);
186
		if(n->complex >= FNX) {
187
			sugen(*fnxp, tn2, n->type->width);
188
			(*fnxp)++;
189
		} else
190
			sugen(n, tn2, n->type->width);
191
		return;
192
	}
193
	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
194
		regaalloc1(tn1, n);
195
		if(n->complex >= FNX) {
196
			cgen(*fnxp, tn1);
197
			(*fnxp)++;
198
		} else
199
			cgen(n, tn1);
200
		return;
201
	}
202
	if(vconst(n) == 0) {
203
		regaalloc(tn2, n);
204
		gopcode(OAS, n, Z, tn2);
205
		return;
206
	}
207
	regalloc(tn1, n, Z);
208
	if(n->complex >= FNX) {
209
		cgen(*fnxp, tn1);
210
		(*fnxp)++;
211
	} else
212
		cgen(n, tn1);
213
	regaalloc(tn2, n);
214
	gopcode(OAS, tn1, Z, tn2);
215
	regfree(tn1);
216
}
217
 
218
Node*
219
nod32const(vlong v)
220
{
221
	constnode.vconst = v & MASK(32);
222
	return &constnode;
223
}
224
 
225
Node*
226
nodconst(long v)
227
{
228
	constnode.vconst = v;
229
	return &constnode;
230
}
231
 
232
Node*
233
nodfconst(double d)
234
{
235
	fconstnode.fconst = d;
236
	return &fconstnode;
237
}
238
 
239
void
240
nodreg(Node *n, Node *nn, int reg)
241
{
242
	*n = regnode;
243
	n->reg = reg;
244
	n->type = nn->type;
245
	n->lineno = nn->lineno;
246
}
247
 
248
void
249
regret(Node *n, Node *nn)
250
{
251
	int r;
252
 
253
	r = REGRET;
254
	if(typefd[nn->type->etype])
255
		r = FREGRET+NREG;
256
	nodreg(n, nn, r);
257
	reg[r]++;
258
}
259
 
260
void
261
regalloc(Node *n, Node *tn, Node *o)
262
{
263
	int i, j;
264
	static int lasti;
265
 
266
	switch(tn->type->etype) {
267
	case TCHAR:
268
	case TUCHAR:
269
	case TSHORT:
270
	case TUSHORT:
271
	case TINT:
272
	case TUINT:
273
	case TLONG:
274
	case TULONG:
275
	case TIND:
276
		if(o != Z && o->op == OREGISTER) {
277
			i = o->reg;
278
			if(i > 0 && i < NREG)
279
				goto out;
280
		}
281
		j = lasti + REGRET+1;
282
		for(i=REGRET+1; i<NREG; i++) {
283
			if(j >= NREG)
284
				j = REGRET+1;
285
			if(reg[j] == 0) {
286
				i = j;
287
				goto out;
288
			}
289
			j++;
290
		}
291
		diag(tn, "out of fixed registers");
292
		goto err;
293
 
294
	case TFLOAT:
295
	case TDOUBLE:
296
	case TVLONG:
297
		if(o != Z && o->op == OREGISTER) {
298
			i = o->reg;
299
			if(i >= NREG && i < NREG+NREG)
300
				goto out;
301
		}
302
		j = lasti*2 + NREG;
303
		for(i=NREG; i<NREG+NREG; i+=2) {
304
			if(j >= NREG+NREG)
305
				j = NREG;
306
			if(reg[j] == 0) {
307
				i = j;
308
				goto out;
309
			}
310
			j += 2;
311
		}
312
		diag(tn, "out of float registers");
313
		goto err;
314
	}
315
	diag(tn, "unknown type in regalloc: %T", tn->type);
316
err:
317
	i = 0;
318
out:
319
	if(i)
320
		reg[i]++;
321
	lasti++;
322
	if(lasti >= 5)
323
		lasti = 0;
324
	nodreg(n, tn, i);
325
}
326
 
327
void
328
regialloc(Node *n, Node *tn, Node *o)
329
{
330
	Node nod;
331
 
332
	nod = *tn;
333
	nod.type = types[TIND];
334
	regalloc(n, &nod, o);
335
}
336
 
337
void
338
regfree(Node *n)
339
{
340
	int i;
341
 
342
	i = 0;
343
	if(n->op != OREGISTER && n->op != OINDREG)
344
		goto err;
345
	i = n->reg;
346
	if(i < 0 || i >= sizeof(reg))
347
		goto err;
348
	if(reg[i] <= 0)
349
		goto err;
350
	reg[i]--;
351
	return;
352
err:
353
	diag(n, "error in regfree: %d", i);
354
}
355
 
356
void
357
regsalloc(Node *n, Node *nn)
358
{
359
	cursafe = align(cursafe, nn->type, Aaut3);
360
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
361
	*n = *nodsafe;
362
	n->xoffset = -(stkoff + cursafe);
363
	n->type = nn->type;
364
	n->etype = nn->type->etype;
365
	n->lineno = nn->lineno;
366
}
367
 
368
void
369
regaalloc1(Node *n, Node *nn)
370
{
371
	nodreg(n, nn, REGARG);
372
	reg[REGARG]++;
373
	curarg = align(curarg, nn->type, Aarg1);
374
	curarg = align(curarg, nn->type, Aarg2);
375
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
376
}
377
 
378
void
379
regaalloc(Node *n, Node *nn)
380
{
381
	curarg = align(curarg, nn->type, Aarg1);
382
	*n = *nn;
383
	n->op = OINDREG;
384
	n->reg = REGSP;
385
	n->xoffset = curarg + SZ_LONG;
386
	n->complex = 0;
387
	n->addable = 20;
388
	curarg = align(curarg, nn->type, Aarg2);
389
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
390
}
391
 
392
void
393
regind(Node *n, Node *nn)
394
{
395
 
396
	if(n->op != OREGISTER) {
397
		diag(n, "regind not OREGISTER");
398
		return;
399
	}
400
	n->op = OINDREG;
401
	n->type = nn->type;
402
}
403
 
404
void
405
raddr(Node *n, Prog *p)
406
{
407
	Adr a;
408
 
409
	naddr(n, &a);
410
	if(a.type == D_CONST && a.offset == 0) {
411
		a.type = D_REG;
412
		a.reg = 0;
413
	}
414
	if(a.type != D_REG && a.type != D_FREG) {
415
		if(n)
416
			diag(n, "bad in raddr: %O", n->op);
417
		else
418
			diag(n, "bad in raddr: <null>");
419
		p->reg = NREG;
420
	} else
421
		p->reg = a.reg;
422
}
423
 
424
void
425
naddr(Node *n, Adr *a)
426
{
427
	long v;
428
 
429
	a->type = D_NONE;
430
	if(n == Z)
431
		return;
432
	switch(n->op) {
433
	default:
434
	bad:
435
		diag(n, "bad in naddr: %O", n->op);
436
		break;
437
 
438
	case OREGISTER:
439
		a->type = D_REG;
440
		a->sym = S;
441
		a->reg = n->reg;
442
		if(a->reg >= NREG) {
443
			a->type = D_FREG;
444
			a->reg -= NREG;
445
		}
446
		break;
447
 
448
	case OIND:
449
		naddr(n->left, a);
450
		if(a->type == D_REG) {
451
			a->type = D_OREG;
452
			break;
453
		}
454
		if(a->type == D_CONST) {
455
			a->type = D_OREG;
456
			break;
457
		}
458
		goto bad;
459
 
460
	case OINDREG:
461
		a->type = D_OREG;
462
		a->sym = S;
463
		a->offset = n->xoffset;
464
		a->reg = n->reg;
465
		break;
466
 
467
	case ONAME:
468
		a->etype = n->etype;
469
		a->type = D_OREG;
470
		a->name = D_STATIC;
471
		a->sym = n->sym;
472
		a->offset = n->xoffset;
473
		if(n->class == CSTATIC)
474
			break;
475
		if(n->class == CEXTERN || n->class == CGLOBL) {
476
			a->name = D_EXTERN;
477
			break;
478
		}
479
		if(n->class == CAUTO) {
480
			a->name = D_AUTO;
481
			break;
482
		}
483
		if(n->class == CPARAM) {
484
			a->name = D_PARAM;
485
			break;
486
		}
487
		goto bad;
488
 
489
	case OCONST:
490
		a->sym = S;
491
		a->reg = NREG;
492
		if(typefd[n->type->etype]) {
493
			a->type = D_FCONST;
494
			a->dval = n->fconst;
495
		} else {
496
			a->type = D_CONST;
497
			a->offset = n->vconst;
498
		}
499
		break;
500
 
501
	case OADDR:
502
		naddr(n->left, a);
503
		if(a->type == D_OREG) {
504
			a->type = D_CONST;
505
			break;
506
		}
507
		goto bad;
508
 
509
	case OADD:
510
		if(n->left->op == OCONST) {
511
			naddr(n->left, a);
512
			v = a->offset;
513
			naddr(n->right, a);
514
		} else {
515
			naddr(n->right, a);
516
			v = a->offset;
517
			naddr(n->left, a);
518
		}
519
		a->offset += v;
520
		break;
521
 
522
	}
523
}
524
 
525
void
526
fop(int as, int f1, int f2, Node *t)
527
{
528
	Node nod1, nod2, nod3;
529
 
530
	nodreg(&nod1, t, NREG+f1);
531
	nodreg(&nod2, t, NREG+f2);
532
	regalloc(&nod3, t, t);
533
	gopcode(as, &nod1, &nod2, &nod3);
534
	gmove(&nod3, t);
535
	regfree(&nod3);
536
}
537
 
538
void
539
gmove(Node *f, Node *t)
540
{
541
	int ft, tt, a;
542
	Node nod;
543
	Prog *p1;
544
	double d;
545
 
546
	ft = f->type->etype;
547
	tt = t->type->etype;
548
 
549
	if(ft == TDOUBLE && f->op == OCONST) {
550
		d = f->fconst;
551
		if(d == 0.0) {
552
			a = FREGZERO;
553
			goto ffreg;
554
		}
555
		if(d == 0.5) {
556
			a = FREGHALF;
557
			goto ffreg;
558
		}
559
		if(d == 1.0) {
560
			a = FREGONE;
561
			goto ffreg;
562
		}
563
		if(d == 2.0) {
564
			a = FREGTWO;
565
			goto ffreg;
566
		}
567
		if(d == -.5) {
568
			fop(OSUB, FREGHALF, FREGZERO, t);
569
			return;
570
		}
571
		if(d == -1.0) {
572
			fop(OSUB, FREGONE, FREGZERO, t);
573
			return;
574
		}
575
		if(d == -2.0) {
576
			fop(OSUB, FREGTWO, FREGZERO, t);
577
			return;
578
		}
579
		if(d == 1.5) {
580
			fop(OADD, FREGONE, FREGHALF, t);
581
			return;
582
		}
583
		if(d == 2.5) {
584
			fop(OADD, FREGTWO, FREGHALF, t);
585
			return;
586
		}
587
		if(d == 3.0) {
588
			fop(OADD, FREGTWO, FREGONE, t);
589
			return;
590
		}
591
	}
592
	if(ft == TFLOAT && f->op == OCONST) {
593
		d = f->fconst;
594
		if(d == 0) {
595
			a = FREGZERO;
596
		ffreg:
597
			nodreg(&nod, f, NREG+a);
598
			gmove(&nod, t);
599
			return;
600
		}
601
	}
602
	/*
603
	 * a load --
604
	 * put it into a register then
605
	 * worry what to do with it.
606
	 */
607
	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
608
		switch(ft) {
609
		default:
610
			if(typefd[tt]) {
611
				/* special case can load mem to Freg */
612
				regalloc(&nod, t, t);
613
				gins(AMOVW, f, &nod);
614
				a = AFMOVWD;
615
				if(tt == TFLOAT)
616
					a = AFMOVWF;
617
				gins(a, &nod, &nod);
618
				gmove(&nod, t);
619
				regfree(&nod);
620
				return;
621
			}
622
			a = AMOVW;
623
			break;
624
		case TFLOAT:
625
			a = AFMOVF;
626
			break;
627
		case TDOUBLE:
628
			a = AFMOVD;
629
			break;
630
		case TCHAR:
631
			a = AMOVB;
632
			break;
633
		case TUCHAR:
634
			a = AMOVBU;
635
			break;
636
		case TSHORT:
637
			a = AMOVH;
638
			break;
639
		case TUSHORT:
640
			a = AMOVHU;
641
			break;
642
		}
643
		regalloc(&nod, f, t);
644
		gins(a, f, &nod);
645
		gmove(&nod, t);
646
		regfree(&nod);
647
		return;
648
	}
649
 
650
	/*
651
	 * a store --
652
	 * put it into a register then
653
	 * store it.
654
	 */
655
	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
656
		switch(tt) {
657
		default:
658
			if(typefd[ft]) {
659
				/* special case can store mem from Freg */
660
				regalloc(&nod, f, Z);
661
				a = AFMOVDW;
662
				if(ft == TFLOAT)
663
					a = AFMOVFW;
664
				gins(a, f, &nod);
665
				gins(AMOVW, &nod, t);
666
				regfree(&nod);
667
				return;
668
			}
669
			a = AMOVW;
670
			break;
671
		case TUCHAR:
672
			a = AMOVBU;
673
			break;
674
		case TCHAR:
675
			a = AMOVB;
676
			break;
677
		case TUSHORT:
678
			a = AMOVHU;
679
			break;
680
		case TSHORT:
681
			a = AMOVH;
682
			break;
683
		case TFLOAT:
684
			a = AFMOVF;
685
			break;
686
		case TVLONG:
687
		case TDOUBLE:
688
			a = AFMOVD;
689
			break;
690
		}
691
		if(!typefd[ft] && vconst(f) == 0) {
692
			gins(a, f, t);
693
			return;
694
		}
695
		if(ft == tt)
696
			regalloc(&nod, t, f);
697
		else
698
			regalloc(&nod, t, Z);
699
		gmove(f, &nod);
700
		gins(a, &nod, t);
701
		regfree(&nod);
702
		return;
703
	}
704
 
705
	/*
706
	 * type x type cross table
707
	 */
708
	a = AGOK;
709
	switch(ft) {
710
	case TDOUBLE:
711
	case TVLONG:
712
	case TFLOAT:
713
		switch(tt) {
714
		case TDOUBLE:
715
		case TVLONG:
716
			a = AFMOVD;
717
			if(ft == TFLOAT)
718
				a = AFMOVFD;
719
			break;
720
		case TFLOAT:
721
			a = AFMOVDF;
722
			if(ft == TFLOAT)
723
				a = AFMOVF;
724
			break;
725
		case TLONG:
726
		case TULONG:
727
		case TIND:
728
		case TINT:
729
		case TUINT:
730
		case TSHORT:
731
		case TUSHORT:
732
		case TCHAR:
733
		case TUCHAR:
734
			regalloc(&nod, f, Z);	/* should be type float */
735
			a = AFMOVDW;
736
			if(ft == TFLOAT)
737
				a = AFMOVFW;
738
			gins(a, f, &nod);
739
			gins(AFMOVF, &nod, nodrat);
740
			regfree(&nod);
741
			gins(AMOVW, nodrat, t);
742
			gmove(t, t);
743
			if(nrathole < SZ_LONG)
744
				nrathole = SZ_LONG;
745
			return;
746
		}
747
		break;
748
	case TINT:
749
	case TUINT:
750
	case TLONG:
751
	case TULONG:
752
	case TIND:
753
		switch(tt) {
754
		case TDOUBLE:
755
		case TVLONG:
756
		case TFLOAT:
757
			goto fxtofl;
758
		case TLONG:
759
		case TULONG:
760
		case TINT:
761
		case TUINT:
762
		case TIND:
763
		case TSHORT:
764
		case TUSHORT:
765
		case TCHAR:
766
		case TUCHAR:
767
			a = AMOVW;
768
			break;
769
		}
770
		break;
771
	case TSHORT:
772
		switch(tt) {
773
		case TDOUBLE:
774
		case TVLONG:
775
		case TFLOAT:
776
			goto fxtofl;
777
		case TUINT:
778
		case TINT:
779
		case TULONG:
780
		case TLONG:
781
		case TIND:
782
			a = AMOVH;
783
			break;
784
		case TSHORT:
785
		case TUSHORT:
786
		case TCHAR:
787
		case TUCHAR:
788
			a = AMOVW;
789
			break;
790
		}
791
		break;
792
	case TUSHORT:
793
		switch(tt) {
794
		case TDOUBLE:
795
		case TVLONG:
796
		case TFLOAT:
797
			goto fxtofl;
798
		case TINT:
799
		case TUINT:
800
		case TLONG:
801
		case TULONG:
802
		case TIND:
803
			a = AMOVHU;
804
			break;
805
		case TSHORT:
806
		case TUSHORT:
807
		case TCHAR:
808
		case TUCHAR:
809
			a = AMOVW;
810
			break;
811
		}
812
		break;
813
	case TCHAR:
814
		switch(tt) {
815
		case TDOUBLE:
816
		case TVLONG:
817
		case TFLOAT:
818
			goto fxtofl;
819
		case TINT:
820
		case TUINT:
821
		case TLONG:
822
		case TULONG:
823
		case TIND:
824
		case TSHORT:
825
		case TUSHORT:
826
			a = AMOVB;
827
			break;
828
		case TCHAR:
829
		case TUCHAR:
830
			a = AMOVW;
831
			break;
832
		}
833
		break;
834
	case TUCHAR:
835
		switch(tt) {
836
		case TDOUBLE:
837
		case TVLONG:
838
		case TFLOAT:
839
		fxtofl:
840
			regalloc(&nod, t, t);	/* should be type float */
841
			gins(AMOVW, f, nodrat);
842
			gins(AFMOVF, nodrat, &nod);
843
			a = AFMOVWD;
844
			if(tt == TFLOAT)
845
				a = AFMOVWF;
846
			gins(a, &nod, t);
847
			regfree(&nod);
848
			if(nrathole < SZ_LONG)
849
				nrathole = SZ_LONG;
850
			if(ft == TULONG) {
851
				regalloc(&nod, t, Z);
852
				if(tt == TFLOAT) {
853
					gins(AFCMPF, t, Z);
854
					p->to.type = D_FREG;
855
					p->to.reg = FREGZERO;
856
					gins(AFBGE, Z, Z);
857
					p1 = p;
858
					gins(AFMOVF, nodfconst(4294967296.), &nod);
859
					gins(AFADDF, &nod, t);
860
				} else {
861
					gins(AFCMPD, t, Z);
862
					p->to.type = D_FREG;
863
					p->to.reg = FREGZERO;
864
					gins(AFBGE, Z, Z);
865
					p1 = p;
866
					gins(AFMOVD, nodfconst(4294967296.), &nod);
867
					gins(AFADDD, &nod, t);
868
				}
869
				patch(p1, pc);
870
				regfree(&nod);
871
			}
872
			return;
873
		case TINT:
874
		case TUINT:
875
		case TLONG:
876
		case TULONG:
877
		case TIND:
878
		case TSHORT:
879
		case TUSHORT:
880
			a = AMOVBU;
881
			break;
882
		case TCHAR:
883
		case TUCHAR:
884
			a = AMOVW;
885
			break;
886
		}
887
		break;
888
	}
889
	if(a == AGOK)
890
		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
891
	if(a == AMOVW || a == AFMOVF || a == AFMOVD)
892
	if(samaddr(f, t))
893
		return;
894
	gins(a, f, t);
895
}
896
 
897
void
898
gins(int a, Node *f, Node *t)
899
{
900
 
901
	nextpc();
902
	p->as = a;
903
	if(f != Z)
904
		naddr(f, &p->from);
905
	if(t != Z)
906
		naddr(t, &p->to);
907
	if(debug['g'])
908
		print("%P\n", p);
909
}
910
 
911
void
912
gopcode(int o, Node *f1, Node *f2, Node *t)
913
{
914
	int a, et;
915
	Adr ta;
916
 
917
	et = TLONG;
918
	if(f1 != Z && f1->type != T)
919
		et = f1->type->etype;
920
	a = AGOK;
921
	switch(o) {
922
	case OAS:
923
		gmove(f1, t);
924
		return;
925
 
926
	case OASADD:
927
	case OADD:
928
		a = AADD;
929
		if(et == TFLOAT)
930
			a = AFADDF;
931
		else
932
		if(et == TDOUBLE || et == TVLONG)
933
			a = AFADDD;
934
		break;
935
 
936
	case OASSUB:
937
	case OSUB:
938
		a = ASUB;
939
		if(et == TFLOAT)
940
			a = AFSUBF;
941
		else
942
		if(et == TDOUBLE || et == TVLONG)
943
			a = AFSUBD;
944
		break;
945
 
946
	case OASOR:
947
	case OOR:
948
		a = AOR;
949
		break;
950
 
951
	case OASAND:
952
	case OAND:
953
		a = AAND;
954
		break;
955
 
956
	case OASXOR:
957
	case OXOR:
958
		a = AXOR;
959
		break;
960
 
961
	case OASLSHR:
962
	case OLSHR:
963
		a = ASRL;
964
		break;
965
 
966
	case OASASHR:
967
	case OASHR:
968
		a = ASRA;
969
		break;
970
 
971
	case OASASHL:
972
	case OASHL:
973
		a = ASLL;
974
		break;
975
 
976
	case OFUNC:
977
		a = AJMPL;
978
		break;
979
 
980
	case OASLMUL:
981
	case OLMUL:
982
	case OASMUL:
983
	case OMUL:
984
		if(et == TFLOAT) {
985
			a = AFMULF;
986
			break;
987
		} else
988
		if(et == TDOUBLE || et == TVLONG) {
989
			a = AFMULD;
990
			break;
991
		}
992
		a = AMUL;
993
		break;
994
 
995
	case OASDIV:
996
	case ODIV:
997
		if(et == TFLOAT) {
998
			a = AFDIVF;
999
			break;
1000
		} else
1001
		if(et == TDOUBLE || et == TVLONG) {
1002
			a = AFDIVD;
1003
			break;
1004
		}
1005
		a = ADIV;
1006
		break;
1007
 
1008
	case OASMOD:
1009
	case OMOD:
1010
		a = AMOD;
1011
		break;
1012
 
1013
	case OASLMOD:
1014
	case OLMOD:
1015
		a = AMODL;
1016
		break;
1017
 
1018
	case OASLDIV:
1019
	case OLDIV:
1020
		a = ADIVL;
1021
		break;
1022
 
1023
	case OEQ:
1024
		a = ABE;
1025
		if(typefd[et])
1026
			a = AFBE;
1027
		goto cmp;
1028
 
1029
	case ONE:
1030
		a = ABNE;
1031
		if(typefd[et])
1032
			a = AFBLG;
1033
		goto cmp;
1034
 
1035
	case OLT:
1036
		a = ABL;
1037
		if(typefd[et])
1038
			a = AFBL;
1039
		goto cmp;
1040
 
1041
	case OLE:
1042
		a = ABLE;
1043
		if(typefd[et])
1044
			a = AFBLE;
1045
		goto cmp;
1046
 
1047
	case OGE:
1048
		a = ABGE;
1049
		if(typefd[et])
1050
			a = AFBGE;
1051
		goto cmp;
1052
 
1053
	case OGT:
1054
		a = ABG;
1055
		if(typefd[et])
1056
			a = AFBG;
1057
		goto cmp;
1058
 
1059
	case OLO:
1060
		a = ABCS;
1061
		goto cmp;
1062
 
1063
	case OLS:
1064
		a = ABLEU;
1065
		goto cmp;
1066
 
1067
	case OHS:
1068
		a = ABCC;
1069
		goto cmp;
1070
 
1071
	case OHI:
1072
		a = ABGU;
1073
		goto cmp;
1074
 
1075
	cmp:
1076
		nextpc();
1077
		p->as = ACMP;
1078
		if(et == TFLOAT)
1079
			p->as = AFCMPF;
1080
		else
1081
		if(et == TDOUBLE || et == TVLONG)
1082
			p->as = AFCMPD;
1083
		if(f1 != Z)
1084
			naddr(f1, &p->from);
1085
		if(t != Z)
1086
			naddr(t, &p->to);
1087
		if(f1 == Z || t == Z || f2 != Z)
1088
			diag(Z, "bad cmp in gopcode %O", o);
1089
		if(debug['g'])
1090
			print("%P\n", p);
1091
		f1 = Z;
1092
		f2 = Z;
1093
		t = Z;
1094
		break;
1095
	}
1096
	if(a == AGOK)
1097
		diag(Z, "bad in gopcode %O", o);
1098
	nextpc();
1099
	p->as = a;
1100
	if(f1 != Z)
1101
		naddr(f1, &p->from);
1102
	if(f2 != Z) {
1103
		naddr(f2, &ta);
1104
		p->reg = ta.reg;
1105
		if(ta.type == D_CONST && ta.offset == 0)
1106
			p->reg = REGZERO;
1107
	}
1108
	if(t != Z)
1109
		naddr(t, &p->to);
1110
	if(debug['g'])
1111
		print("%P\n", p);
1112
}
1113
 
1114
samaddr(Node *f, Node *t)
1115
{
1116
 
1117
	if(f->op != t->op)
1118
		return 0;
1119
	switch(f->op) {
1120
 
1121
	case OREGISTER:
1122
		if(f->reg != t->reg)
1123
			break;
1124
		return 1;
1125
	}
1126
	return 0;
1127
}
1128
 
1129
void
1130
gbranch(int o)
1131
{
1132
	int a;
1133
 
1134
	a = AGOK;
1135
	switch(o) {
1136
	case ORETURN:
1137
		a = ARETURN;
1138
		break;
1139
	case OGOTO:
1140
		a = AJMP;
1141
		break;
1142
	}
1143
	nextpc();
1144
	if(a == AGOK) {
1145
		diag(Z, "bad in gbranch %O",  o);
1146
		nextpc();
1147
	}
1148
	p->as = a;
1149
}
1150
 
1151
void
1152
patch(Prog *op, long pc)
1153
{
1154
 
1155
	op->to.offset = pc;
1156
	op->to.type = D_BRANCH;
1157
}
1158
 
1159
void
1160
gpseudo(int a, Sym *s, Node *n)
1161
{
1162
 
1163
	nextpc();
1164
	p->as = a;
1165
	p->from.type = D_OREG;
1166
	p->from.sym = s;
1167
	if(a == ATEXT)
1168
		p->reg = (profileflg ? 0 : NOPROF);
1169
	p->from.name = D_EXTERN;
1170
	if(s->class == CSTATIC)
1171
		p->from.name = D_STATIC;
1172
	naddr(n, &p->to);
1173
	if(a == ADATA || a == AGLOBL)
1174
		pc--;
1175
}
1176
 
1177
int
1178
sval(long v)
1179
{
1180
 
1181
	if(v >= -(1<<12) && v < (1<<12))
1182
		return 1;
1183
	return 0;
1184
}
1185
 
1186
int
1187
sconst(Node *n)
1188
{
1189
	vlong vv;
1190
 
1191
	if(n->op == OCONST) {
1192
		if(!typefd[n->type->etype]) {
1193
			vv = n->vconst;
1194
			if(vv >= -(vlong)(1<<12) && vv < (vlong)(1<<12))
1195
				return 1;
1196
		}
1197
	}
1198
	return 0;
1199
}
1200
 
1201
long
1202
exreg(Type *t)
1203
{
1204
	long o;
1205
 
1206
	if(typechlp[t->etype]) {
1207
		if(exregoffset <= 3)
1208
			return 0;
1209
		o = exregoffset;
1210
		exregoffset--;
1211
		return o;
1212
	}
1213
	if(typefd[t->etype]) {
1214
		if(exfregoffset <= 16)
1215
			return 0;
1216
		o = exfregoffset + NREG;
1217
		exfregoffset--;
1218
		return o;
1219
	}
1220
	return 0;
1221
}
1222
 
1223
schar	ewidth[NTYPE] =
1224
{
1225
	-1,		/* [TXXX] */
1226
	SZ_CHAR,	/* [TCHAR] */
1227
	SZ_CHAR,	/* [TUCHAR] */
1228
	SZ_SHORT,	/* [TSHORT] */
1229
	SZ_SHORT,	/* [TUSHORT] */
1230
	SZ_INT,		/* [TINT] */
1231
	SZ_INT,		/* [TUINT] */
1232
	SZ_LONG,	/* [TLONG] */
1233
	SZ_LONG,	/* [TULONG] */
1234
	SZ_VLONG,	/* [TVLONG] */
1235
	SZ_VLONG,	/* [TUVLONG] */
1236
	SZ_FLOAT,	/* [TFLOAT] */
1237
	SZ_DOUBLE,	/* [TDOUBLE] */
1238
	SZ_IND,		/* [TIND] */
1239
	0,		/* [TFUNC] */
1240
	-1,		/* [TARRAY] */
1241
	0,		/* [TVOID] */
1242
	-1,		/* [TSTRUCT] */
1243
	-1,		/* [TUNION] */
1244
	SZ_INT,		/* [TENUM] */
1245
};
1246
 
1247
long	ncast[NTYPE] =
1248
{
1249
	0,				/* [TXXX] */
1250
	BCHAR|BUCHAR,			/* [TCHAR] */
1251
	BCHAR|BUCHAR,			/* [TUCHAR] */
1252
	BSHORT|BUSHORT,			/* [TSHORT] */
1253
	BSHORT|BUSHORT,			/* [TUSHORT] */
1254
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1255
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1256
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1257
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1258
	BVLONG|BUVLONG,			/* [TVLONG] */
1259
	BVLONG|BUVLONG,			/* [TUVLONG] */
1260
	BFLOAT,				/* [TFLOAT] */
1261
	BDOUBLE,			/* [TDOUBLE] */
1262
	BLONG|BULONG|BIND,		/* [TIND] */
1263
	0,				/* [TFUNC] */
1264
	0,				/* [TARRAY] */
1265
	0,				/* [TVOID] */
1266
	BSTRUCT,			/* [TSTRUCT] */
1267
	BUNION,				/* [TUNION] */
1268
	0,				/* [TENUM] */
1269
};