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 = 'v';
10
	thestring = "mips";
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 = REGTMP;
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
	for(i=0; i<nelem(reg); i++) {
83
		reg[i] = 0;
84
		if(i == REGZERO ||
85
		  (i >= NREG && ((i-NREG)&1)))
86
			reg[i] = 1;
87
	}
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)
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
nodconst(long v)
220
{
221
	constnode.vconst = v;
222
	return &constnode;
223
}
224
 
225
Node*
226
nod32const(vlong v)
227
{
228
	constnode.vconst = v & MASK(32);
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
int
261
tmpreg(void)
262
{
263
	int i;
264
 
265
	for(i=REGRET+1; i<NREG; i++)
266
		if(reg[i] == 0)
267
			return i;
268
	diag(Z, "out of fixed registers");
269
	return 0;
270
}
271
 
272
void
273
regalloc(Node *n, Node *tn, Node *o)
274
{
275
	int i, j;
276
	static int lasti;
277
 
278
	switch(tn->type->etype) {
279
	case TCHAR:
280
	case TUCHAR:
281
	case TSHORT:
282
	case TUSHORT:
283
	case TINT:
284
	case TUINT:
285
	case TLONG:
286
	case TULONG:
287
	case TIND:
288
		if(o != Z && o->op == OREGISTER) {
289
			i = o->reg;
290
			if(i > 0 && i < NREG)
291
				goto out;
292
		}
293
		j = lasti + REGRET+1;
294
		for(i=REGRET+1; i<NREG; i++) {
295
			if(j >= NREG)
296
				j = REGRET+1;
297
			if(reg[j] == 0) {
298
				i = j;
299
				goto out;
300
			}
301
			j++;
302
		}
303
		diag(tn, "out of fixed registers");
304
		goto err;
305
 
306
	case TFLOAT:
307
	case TDOUBLE:
308
	case TVLONG:
309
		if(o != Z && o->op == OREGISTER) {
310
			i = o->reg;
311
			if(i >= NREG && i < NREG+NREG)
312
				goto out;
313
		}
314
		j = 0*2 + NREG;
315
		for(i=NREG; i<NREG+NREG; i+=2) {
316
			if(j >= NREG+NREG)
317
				j = NREG;
318
			if(reg[j] == 0) {
319
				i = j;
320
				goto out;
321
			}
322
			j += 2;
323
		}
324
		diag(tn, "out of float registers");
325
		goto err;
326
	}
327
	diag(tn, "unknown type in regalloc: %T", tn->type);
328
err:
329
	nodreg(n, tn, 0);
330
	return;
331
out:
332
	reg[i]++;
333
	lasti++;
334
	if(lasti >= 5)
335
		lasti = 0;
336
	nodreg(n, tn, i);
337
}
338
 
339
void
340
regialloc(Node *n, Node *tn, Node *o)
341
{
342
	Node nod;
343
 
344
	nod = *tn;
345
	nod.type = types[TIND];
346
	regalloc(n, &nod, o);
347
}
348
 
349
void
350
regfree(Node *n)
351
{
352
	int i;
353
 
354
	i = 0;
355
	if(n->op != OREGISTER && n->op != OINDREG)
356
		goto err;
357
	i = n->reg;
358
	if(i < 0 || i >= sizeof(reg))
359
		goto err;
360
	if(reg[i] <= 0)
361
		goto err;
362
	reg[i]--;
363
	return;
364
err:
365
	diag(n, "error in regfree: %d", i);
366
}
367
 
368
void
369
regsalloc(Node *n, Node *nn)
370
{
371
	cursafe = align(cursafe, nn->type, Aaut3);
372
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
373
	*n = *nodsafe;
374
	n->xoffset = -(stkoff + cursafe);
375
	n->type = nn->type;
376
	n->etype = nn->type->etype;
377
	n->lineno = nn->lineno;
378
}
379
 
380
void
381
regaalloc1(Node *n, Node *nn)
382
{
383
	nodreg(n, nn, REGARG);
384
	reg[REGARG]++;
385
	curarg = align(curarg, nn->type, Aarg1);
386
	curarg = align(curarg, nn->type, Aarg2);
387
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
388
}
389
 
390
void
391
regaalloc(Node *n, Node *nn)
392
{
393
	curarg = align(curarg, nn->type, Aarg1);
394
	*n = *nn;
395
	n->op = OINDREG;
396
	n->reg = REGSP;
397
	n->xoffset = curarg + SZ_LONG;
398
	n->complex = 0;
399
	n->addable = 20;
400
	curarg = align(curarg, nn->type, Aarg2);
401
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
402
}
403
 
404
void
405
regind(Node *n, Node *nn)
406
{
407
 
408
	if(n->op != OREGISTER) {
409
		diag(n, "regind not OREGISTER");
410
		return;
411
	}
412
	n->op = OINDREG;
413
	n->type = nn->type;
414
}
415
 
416
void
417
raddr(Node *n, Prog *p)
418
{
419
	Adr a;
420
 
421
	naddr(n, &a);
422
	if(a.type == D_CONST && a.offset == 0) {
423
		a.type = D_REG;
424
		a.reg = 0;
425
	}
426
	if(a.type != D_REG && a.type != D_FREG) {
427
		if(n)
428
			diag(n, "bad in raddr: %O", n->op);
429
		else
430
			diag(n, "bad in raddr: <null>");
431
		p->reg = NREG;
432
	} else
433
		p->reg = a.reg;
434
}
435
 
436
void
437
naddr(Node *n, Adr *a)
438
{
439
	long v;
440
 
441
	a->type = D_NONE;
442
	if(n == Z)
443
		return;
444
	switch(n->op) {
445
	default:
446
	bad:
447
		diag(n, "bad in naddr: %O", n->op);
448
		break;
449
 
450
	case OREGISTER:
451
		a->type = D_REG;
452
		a->sym = S;
453
		a->reg = n->reg;
454
		if(a->reg >= NREG) {
455
			a->type = D_FREG;
456
			a->reg -= NREG;
457
		}
458
		break;
459
 
460
	case OIND:
461
		naddr(n->left, a);
462
		if(a->type == D_REG) {
463
			a->type = D_OREG;
464
			break;
465
		}
466
		if(a->type == D_CONST) {
467
			a->type = D_OREG;
468
			break;
469
		}
470
		goto bad;
471
 
472
	case OINDREG:
473
		a->type = D_OREG;
474
		a->sym = S;
475
		a->offset = n->xoffset;
476
		a->reg = n->reg;
477
		break;
478
 
479
	case ONAME:
480
		a->etype = n->etype;
481
		a->type = D_OREG;
482
		a->name = D_STATIC;
483
		a->sym = n->sym;
484
		a->offset = n->xoffset;
485
		if(n->class == CSTATIC)
486
			break;
487
		if(n->class == CEXTERN || n->class == CGLOBL) {
488
			a->name = D_EXTERN;
489
			break;
490
		}
491
		if(n->class == CAUTO) {
492
			a->name = D_AUTO;
493
			break;
494
		}
495
		if(n->class == CPARAM) {
496
			a->name = D_PARAM;
497
			break;
498
		}
499
		goto bad;
500
 
501
	case OCONST:
502
		a->sym = S;
503
		a->reg = NREG;
504
		if(typefd[n->type->etype]) {
505
			a->type = D_FCONST;
506
			a->dval = n->fconst;
507
		} else {
508
			a->type = D_CONST;
509
			a->offset = n->vconst;
510
		}
511
		break;
512
 
513
	case OADDR:
514
		naddr(n->left, a);
515
		if(a->type == D_OREG) {
516
			a->type = D_CONST;
517
			break;
518
		}
519
		goto bad;
520
 
521
	case OADD:
522
		if(n->left->op == OCONST) {
523
			naddr(n->left, a);
524
			v = a->offset;
525
			naddr(n->right, a);
526
		} else {
527
			naddr(n->right, a);
528
			v = a->offset;
529
			naddr(n->left, a);
530
		}
531
		a->offset += v;
532
		break;
533
 
534
	}
535
}
536
 
537
void
538
fop(int as, int f1, int f2, Node *t)
539
{
540
	Node nod1, nod2, nod3;
541
 
542
	nodreg(&nod1, t, NREG+f1);
543
	nodreg(&nod2, t, NREG+f2);
544
	regalloc(&nod3, t, t);
545
	gopcode(as, &nod1, &nod2, &nod3);
546
	gmove(&nod3, t);
547
	regfree(&nod3);
548
}
549
 
550
void
551
gmove(Node *f, Node *t)
552
{
553
	int ft, tt, a;
554
	Node nod, nod1, nod2;
555
	Prog *p1;
556
	double d;
557
 
558
	ft = f->type->etype;
559
	tt = t->type->etype;
560
 
561
	if(ft == TDOUBLE && f->op == OCONST) {
562
		d = f->fconst;
563
		if(d == 0.0) {
564
			a = FREGZERO;
565
			goto ffreg;
566
		}
567
		if(d == 0.5) {
568
			a = FREGHALF;
569
			goto ffreg;
570
		}
571
		if(d == 1.0) {
572
			a = FREGONE;
573
			goto ffreg;
574
		}
575
		if(d == 2.0) {
576
			a = FREGTWO;
577
			goto ffreg;
578
		}
579
		if(d == -.5) {
580
			fop(OSUB, FREGHALF, FREGZERO, t);
581
			return;
582
		}
583
		if(d == -1.0) {
584
			fop(OSUB, FREGONE, FREGZERO, t);
585
			return;
586
		}
587
		if(d == -2.0) {
588
			fop(OSUB, FREGTWO, FREGZERO, t);
589
			return;
590
		}
591
		if(d == 1.5) {
592
			fop(OADD, FREGONE, FREGHALF, t);
593
			return;
594
		}
595
		if(d == 2.5) {
596
			fop(OADD, FREGTWO, FREGHALF, t);
597
			return;
598
		}
599
		if(d == 3.0) {
600
			fop(OADD, FREGTWO, FREGONE, t);
601
			return;
602
		}
603
	}
604
	if(ft == TFLOAT && f->op == OCONST) {
605
		d = f->fconst;
606
		if(d == 0) {
607
			a = FREGZERO;
608
		ffreg:
609
			nodreg(&nod, f, NREG+a);
610
			gmove(&nod, t);
611
			return;
612
		}
613
	}
614
	/*
615
	 * a load --
616
	 * put it into a register then
617
	 * worry what to do with it.
618
	 */
619
	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
620
		switch(ft) {
621
		default:
622
			if(typefd[tt]) {
623
				/* special case can load mem to Freg */
624
				regalloc(&nod, t, t);
625
				gins(AMOVW, f, &nod);
626
				a = AMOVWD;
627
				if(tt == TFLOAT)
628
					a = AMOVWF;
629
				gins(a, &nod, &nod);
630
				gmove(&nod, t);
631
				regfree(&nod);
632
				return;
633
			}
634
			a = AMOVW;
635
			break;
636
		case TFLOAT:
637
			a = AMOVF;
638
			break;
639
		case TDOUBLE:
640
			a = AMOVD;
641
			break;
642
		case TCHAR:
643
			a = AMOVB;
644
			break;
645
		case TUCHAR:
646
			a = AMOVBU;
647
			break;
648
		case TSHORT:
649
			a = AMOVH;
650
			break;
651
		case TUSHORT:
652
			a = AMOVHU;
653
			break;
654
		}
655
		if(typechlp[ft] && typeilp[tt])
656
			regalloc(&nod, t, t);
657
		else
658
			regalloc(&nod, f, t);
659
		gins(a, f, &nod);
660
		gmove(&nod, t);
661
		regfree(&nod);
662
		return;
663
	}
664
 
665
	/*
666
	 * a store --
667
	 * put it into a register then
668
	 * store it.
669
	 */
670
	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
671
		switch(tt) {
672
		default:
673
			a = AMOVW;
674
			break;
675
		case TUCHAR:
676
			a = AMOVBU;
677
			break;
678
		case TCHAR:
679
			a = AMOVB;
680
			break;
681
		case TUSHORT:
682
			a = AMOVHU;
683
			break;
684
		case TSHORT:
685
			a = AMOVH;
686
			break;
687
		case TFLOAT:
688
			a = AMOVF;
689
			break;
690
		case TDOUBLE:
691
			a = AMOVD;
692
			break;
693
		}
694
		if(!typefd[ft] && vconst(f) == 0) {
695
			gins(a, f, t);
696
			return;
697
		}
698
		if(ft == tt)
699
			regalloc(&nod, t, f);
700
		else
701
			regalloc(&nod, t, Z);
702
		gmove(f, &nod);
703
		gins(a, &nod, t);
704
		regfree(&nod);
705
		return;
706
	}
707
 
708
	/*
709
	 * type x type cross table
710
	 */
711
	a = AGOK;
712
	switch(ft) {
713
	case TDOUBLE:
714
	case TVLONG:
715
	case TFLOAT:
716
		switch(tt) {
717
		case TDOUBLE:
718
		case TVLONG:
719
			a = AMOVD;
720
			if(ft == TFLOAT)
721
				a = AMOVFD;
722
			break;
723
		case TFLOAT:
724
			a = AMOVDF;
725
			if(ft == TFLOAT)
726
				a = AMOVF;
727
			break;
728
		case TINT:
729
		case TUINT:
730
		case TLONG:
731
		case TULONG:
732
		case TIND:
733
		case TSHORT:
734
		case TUSHORT:
735
		case TCHAR:
736
		case TUCHAR:
737
			if(fproundflg) {
738
				/* convert f, t */
739
				regalloc(&nod, f, Z);
740
				gins(AMOVDW, f, &nod);
741
				if(ft == TFLOAT)
742
					p->as = AMOVFW;
743
				gins(AMOVW, &nod, t);
744
				regfree(&nod);
745
				gins(AMOVW, t, t);
746
				return;
747
			}
748
			regalloc(&nod1, &regnode, Z);
749
			regalloc(&nod2, &regnode, Z);
750
 
751
			/* movw fcr, rx */
752
			gins(AMOVW, Z, &nod1);
753
			p->from.type = D_FCREG;
754
			p->from.reg = 31;
755
 
756
			/* nop */
757
			gins(ANOR, nodconst(0), nodconst(0));
758
			p->to.type = D_REG;
759
			p->to.reg = 0;
760
 
761
			/* nop */
762
			gins(ANOR, nodconst(0), nodconst(0));
763
			p->to.type = D_REG;
764
			p->to.reg = 0;
765
 
766
			/* or $3, rx, ry */
767
			gins(AOR, nodconst(3), &nod2);
768
			p->reg = nod1.reg;
769
 
770
			/* xor $2, ry */
771
			gins(AXOR, nodconst(2), &nod2);
772
 
773
			/* movw ry, fcr */
774
			gins(AMOVW, &nod2, Z);
775
			p->to.type = D_FCREG;
776
			p->to.reg = 31;
777
 
778
			/* nop */
779
			gins(ANOR, nodconst(0), nodconst(0));
780
			p->to.type = D_REG;
781
			p->to.reg = 0;
782
 
783
			/* nop */
784
			gins(ANOR, nodconst(0), nodconst(0));
785
			p->to.type = D_REG;
786
			p->to.reg = 0;
787
 
788
			/* convert f, t */
789
			regalloc(&nod, f, Z);
790
			gins(AMOVDW, f, &nod);
791
			if(ft == TFLOAT)
792
				p->as = AMOVFW;
793
			gins(AMOVW, &nod, t);
794
			regfree(&nod);
795
			gins(AMOVW, t, t);
796
 
797
			/* movw rx, fcr */
798
			gins(AMOVW, &nod1, Z);
799
			p->to.type = D_FCREG;
800
			p->to.reg = 31;
801
 
802
			/* nop */
803
			gins(ANOR, nodconst(0), nodconst(0));
804
			p->to.type = D_REG;
805
			p->to.reg = 0;
806
 
807
			/* nop */
808
			gins(ANOR, nodconst(0), nodconst(0));
809
			p->to.type = D_REG;
810
			p->to.reg = 0;
811
 
812
			regfree(&nod1);
813
			regfree(&nod2);
814
			return;
815
		}
816
		break;
817
	case TINT:
818
	case TUINT:
819
	case TLONG:
820
	case TULONG:
821
	case TIND:
822
		switch(tt) {
823
		case TDOUBLE:
824
		case TVLONG:
825
			gins(AMOVW, f, t);
826
			gins(AMOVWD, t, t);
827
			if(ft == TULONG || ft == TUINT) {
828
				regalloc(&nod, t, Z);
829
				gins(ACMPGED, t, Z);
830
				p->reg = FREGZERO;
831
				gins(ABFPT, Z, Z);
832
				p1 = p;
833
				gins(AMOVD, nodfconst(4294967296.), &nod);
834
				gins(AADDD, &nod, t);
835
				patch(p1, pc);
836
				regfree(&nod);
837
			}
838
			return;
839
		case TFLOAT:
840
			gins(AMOVW, f, t);
841
			gins(AMOVWF, t, t);
842
			if(ft == TULONG || ft == TUINT) {
843
				regalloc(&nod, t, Z);
844
				gins(ACMPGEF, t, Z);
845
				p->reg = FREGZERO;
846
				gins(ABFPT, Z, Z);
847
				p1 = p;
848
				gins(AMOVF, nodfconst(4294967296.), &nod);
849
				gins(AADDF, &nod, t);
850
				patch(p1, pc);
851
				regfree(&nod);
852
			}
853
			return;
854
		case TINT:
855
		case TUINT:
856
		case TLONG:
857
		case TULONG:
858
		case TIND:
859
		case TSHORT:
860
		case TUSHORT:
861
		case TCHAR:
862
		case TUCHAR:
863
			a = AMOVW;
864
			break;
865
		}
866
		break;
867
	case TSHORT:
868
		switch(tt) {
869
		case TDOUBLE:
870
		case TVLONG:
871
			regalloc(&nod, f, Z);
872
			gins(AMOVH, f, &nod);
873
			gins(AMOVW, &nod, t);
874
			gins(AMOVWD, t, t);
875
			regfree(&nod);
876
			return;
877
		case TFLOAT:
878
			regalloc(&nod, f, Z);
879
			gins(AMOVH, f, &nod);
880
			gins(AMOVW, &nod, t);
881
			gins(AMOVWF, t, t);
882
			regfree(&nod);
883
			return;
884
		case TINT:
885
		case TUINT:
886
		case TLONG:
887
		case TULONG:
888
		case TIND:
889
			a = AMOVH;
890
			break;
891
		case TSHORT:
892
		case TUSHORT:
893
		case TCHAR:
894
		case TUCHAR:
895
			a = AMOVW;
896
			break;
897
		}
898
		break;
899
	case TUSHORT:
900
		switch(tt) {
901
		case TDOUBLE:
902
		case TVLONG:
903
			regalloc(&nod, f, Z);
904
			gins(AMOVHU, f, &nod);
905
			gins(AMOVW, &nod, t);
906
			gins(AMOVWD, t, t);
907
			regfree(&nod);
908
			return;
909
		case TFLOAT:
910
			regalloc(&nod, f, Z);
911
			gins(AMOVHU, f, &nod);
912
			gins(AMOVW, &nod, t);
913
			gins(AMOVWF, t, t);
914
			regfree(&nod);
915
			return;
916
		case TINT:
917
		case TUINT:
918
		case TLONG:
919
		case TULONG:
920
		case TIND:
921
			a = AMOVHU;
922
			break;
923
		case TSHORT:
924
		case TUSHORT:
925
		case TCHAR:
926
		case TUCHAR:
927
			a = AMOVW;
928
			break;
929
		}
930
		break;
931
	case TCHAR:
932
		switch(tt) {
933
		case TDOUBLE:
934
		case TVLONG:
935
			regalloc(&nod, f, Z);
936
			gins(AMOVB, f, &nod);
937
			gins(AMOVW, &nod, t);
938
			gins(AMOVWD, t, t);
939
			regfree(&nod);
940
			return;
941
		case TFLOAT:
942
			regalloc(&nod, f, Z);
943
			gins(AMOVB, f, &nod);
944
			gins(AMOVW, &nod, t);
945
			gins(AMOVWF, t, t);
946
			regfree(&nod);
947
			return;
948
		case TINT:
949
		case TUINT:
950
		case TLONG:
951
		case TULONG:
952
		case TIND:
953
		case TSHORT:
954
		case TUSHORT:
955
			a = AMOVB;
956
			break;
957
		case TCHAR:
958
		case TUCHAR:
959
			a = AMOVW;
960
			break;
961
		}
962
		break;
963
	case TUCHAR:
964
		switch(tt) {
965
		case TDOUBLE:
966
		case TVLONG:
967
			regalloc(&nod, f, Z);
968
			gins(AMOVBU, f, &nod);
969
			gins(AMOVW, &nod, t);
970
			gins(AMOVWD, t, t);
971
			regfree(&nod);
972
			return;
973
		case TFLOAT:
974
			regalloc(&nod, f, Z);
975
			gins(AMOVBU, f, &nod);
976
			gins(AMOVW, &nod, t);
977
			gins(AMOVWF, t, t);
978
			regfree(&nod);
979
			return;
980
		case TINT:
981
		case TUINT:
982
		case TLONG:
983
		case TULONG:
984
		case TIND:
985
		case TSHORT:
986
		case TUSHORT:
987
			a = AMOVBU;
988
			break;
989
		case TCHAR:
990
		case TUCHAR:
991
			a = AMOVW;
992
			break;
993
		}
994
		break;
995
	}
996
	if(a == AGOK)
997
		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
998
	if(a == AMOVW || a == AMOVF || a == AMOVD)
999
	if(samaddr(f, t))
1000
		return;
1001
	gins(a, f, t);
1002
}
1003
 
1004
void
1005
gins(int a, Node *f, Node *t)
1006
{
1007
 
1008
	nextpc();
1009
	p->as = a;
1010
	if(f != Z)
1011
		naddr(f, &p->from);
1012
	if(t != Z)
1013
		naddr(t, &p->to);
1014
	if(debug['g'])
1015
		print("%P\n", p);
1016
}
1017
 
1018
void
1019
gopcode(int o, Node *f1, Node *f2, Node *t)
1020
{
1021
	int a, et;
1022
	Adr ta;
1023
 
1024
	et = TLONG;
1025
	if(f1 != Z && f1->type != T)
1026
		et = f1->type->etype;
1027
	a = AGOK;
1028
	switch(o) {
1029
	case OAS:
1030
		gmove(f1, t);
1031
		return;
1032
 
1033
	case OASADD:
1034
	case OADD:
1035
		a = AADDU;
1036
		if(et == TFLOAT)
1037
			a = AADDF;
1038
		else
1039
		if(et == TDOUBLE || et == TVLONG)
1040
			a = AADDD;
1041
		break;
1042
 
1043
	case OASSUB:
1044
	case OSUB:
1045
		a = ASUBU;
1046
		if(et == TFLOAT)
1047
			a = ASUBF;
1048
		else
1049
		if(et == TDOUBLE || et == TVLONG)
1050
			a = ASUBD;
1051
		break;
1052
 
1053
	case OASOR:
1054
	case OOR:
1055
		a = AOR;
1056
		break;
1057
 
1058
	case OASAND:
1059
	case OAND:
1060
		a = AAND;
1061
		break;
1062
 
1063
	case OASXOR:
1064
	case OXOR:
1065
		a = AXOR;
1066
		break;
1067
 
1068
	case OASLSHR:
1069
	case OLSHR:
1070
		a = ASRL;
1071
		break;
1072
 
1073
	case OASASHR:
1074
	case OASHR:
1075
		a = ASRA;
1076
		break;
1077
 
1078
	case OASASHL:
1079
	case OASHL:
1080
		a = ASLL;
1081
		break;
1082
 
1083
	case OFUNC:
1084
		a = AJAL;
1085
		break;
1086
 
1087
	case OCOND:
1088
		a = ASGTU;
1089
		break;
1090
 
1091
	case OCOMMA:
1092
		a = ASGT;
1093
		break;
1094
 
1095
	case OASMUL:
1096
	case OMUL:
1097
		if(et == TFLOAT) {
1098
			a = AMULF;
1099
			break;
1100
		} else
1101
		if(et == TDOUBLE || et == TVLONG) {
1102
			a = AMULD;
1103
			break;
1104
		}
1105
		a = AMUL;
1106
		goto muldiv;
1107
 
1108
	case OASDIV:
1109
	case ODIV:
1110
		if(et == TFLOAT) {
1111
			a = ADIVF;
1112
			break;
1113
		} else
1114
		if(et == TDOUBLE || et == TVLONG) {
1115
			a = ADIVD;
1116
			break;
1117
		}
1118
		a = ADIV;
1119
		goto muldiv;
1120
 
1121
	case OASMOD:
1122
	case OMOD:
1123
		a = ADIV;
1124
		o = OMOD;
1125
		goto muldiv;
1126
 
1127
	case OASLMUL:
1128
	case OLMUL:
1129
		a = AMULU;
1130
		goto muldiv;
1131
 
1132
	case OASLMOD:
1133
	case OLMOD:
1134
		a = ADIVU;
1135
		o = OMOD;
1136
		goto muldiv;
1137
 
1138
	case OASLDIV:
1139
	case OLDIV:
1140
		a = ADIVU;
1141
		goto muldiv;
1142
 
1143
	muldiv:
1144
		nextpc();
1145
		naddr(f1, &p->from);
1146
		if(f2 == Z)
1147
			raddr(t, p);
1148
		else
1149
			raddr(f2, p);
1150
		p->as = a;
1151
		if(debug['g'])
1152
			print("%P\n", p);
1153
 
1154
		nextpc();
1155
		p->as = AMOVW;
1156
		a = D_LO;
1157
		if(o == OMOD)
1158
			a = D_HI;
1159
		p->from.type = a;
1160
		naddr(t, &p->to);
1161
		if(debug['g'])
1162
			print("%P\n", p);
1163
		return;
1164
 
1165
	case OEQ:
1166
		if(!typefd[et]) {
1167
			a = ABEQ;
1168
			break;
1169
		}
1170
 
1171
	case ONE:
1172
		if(!typefd[et]) {
1173
			a = ABNE;
1174
			break;
1175
		}
1176
 
1177
	case OLT:
1178
	case OLE:
1179
	case OGE:
1180
	case OGT:
1181
		if(typefd[et]) {
1182
			nextpc();
1183
			if(et == TFLOAT) {
1184
				a = ACMPGTF;
1185
				if(o == OEQ || o == ONE)
1186
					a = ACMPEQF;
1187
				else
1188
				if(o == OLT || o == OGE)
1189
					a = ACMPGEF;
1190
			} else {
1191
				a = ACMPGTD;
1192
				if(o == OEQ || o == ONE)
1193
					a = ACMPEQD;
1194
				else
1195
				if(o == OLT || o == OGE)
1196
					a = ACMPGED;
1197
			}
1198
			p->as = a;
1199
			naddr(f1, &p->from);
1200
			raddr(f2, p);
1201
			if(debug['g'])
1202
				print("%P\n", p);
1203
			nextpc();
1204
			a = ABFPF;
1205
			if(o == OEQ || o == OGE || o == OGT)
1206
				a = ABFPT;
1207
			p->as = a;
1208
			if(debug['g'])
1209
				print("%P\n", p);
1210
			return;
1211
		}
1212
		if(vconst(f1) == 0 || vconst(f2) == 0) {
1213
			if(vconst(f1) == 0) {
1214
				o = invrel[relindex(o)];
1215
				f1 = f2;
1216
			}
1217
			switch(o) {
1218
			case OLT:
1219
				a = ABLTZ;
1220
				break;
1221
			case OLE:
1222
				a = ABLEZ;
1223
				break;
1224
			case OGE:
1225
				a = ABGEZ;
1226
				break;
1227
			case OGT:
1228
				a = ABGTZ;
1229
				break;
1230
			}
1231
			f2 = Z;
1232
			break;
1233
		}
1234
 
1235
	case OLO:
1236
	case OLS:
1237
	case OHS:
1238
	case OHI:
1239
		nextpc();
1240
		if(o == OLE || o == OGT || o == OLS || o == OHI) {
1241
			naddr(f1, &p->from);
1242
			raddr(f2, p);
1243
		} else {
1244
			naddr(f2, &p->from);
1245
			raddr(f1, p);
1246
		}
1247
		naddr(&regnode, &p->to);
1248
		p->to.reg = tmpreg();
1249
		a = ASGT;
1250
		if(o == OLO || o == OLS || o == OHS || o == OHI)
1251
			a = ASGTU;
1252
		p->as = a;
1253
		if(debug['g'])
1254
			print("%P\n", p);
1255
 
1256
		nextpc();
1257
		naddr(&regnode, &p->from);
1258
		p->from.reg = tmpreg();
1259
		a = ABEQ;
1260
		if(o == OLT || o == OGT || o == OLO || o == OHI)
1261
			a = ABNE;
1262
		p->as = a;
1263
		if(debug['g'])
1264
			print("%P\n", p);
1265
		return;
1266
	}
1267
	if(a == AGOK)
1268
		diag(Z, "bad in gopcode %O", o);
1269
	nextpc();
1270
	p->as = a;
1271
	if(f1 != Z)
1272
		naddr(f1, &p->from);
1273
	if(f2 != Z) {
1274
		naddr(f2, &ta);
1275
		p->reg = ta.reg;
1276
		if(ta.type == D_CONST && ta.offset == 0)
1277
			p->reg = REGZERO;
1278
	}
1279
	if(t != Z)
1280
		naddr(t, &p->to);
1281
	if(debug['g'])
1282
		print("%P\n", p);
1283
}
1284
 
1285
int
1286
samaddr(Node *f, Node *t)
1287
{
1288
 
1289
	if(f->op != t->op)
1290
		return 0;
1291
	switch(f->op) {
1292
 
1293
	case OREGISTER:
1294
		if(f->reg != t->reg)
1295
			break;
1296
		return 1;
1297
	}
1298
	return 0;
1299
}
1300
 
1301
void
1302
gbranch(int o)
1303
{
1304
	int a;
1305
 
1306
	a = AGOK;
1307
	switch(o) {
1308
	case ORETURN:
1309
		a = ARET;
1310
		break;
1311
	case OGOTO:
1312
		a = AJMP;
1313
		break;
1314
	}
1315
	nextpc();
1316
	if(a == AGOK) {
1317
		diag(Z, "bad in gbranch %O",  o);
1318
		nextpc();
1319
	}
1320
	p->as = a;
1321
}
1322
 
1323
void
1324
patch(Prog *op, long pc)
1325
{
1326
 
1327
	op->to.offset = pc;
1328
	op->to.type = D_BRANCH;
1329
}
1330
 
1331
void
1332
gpseudo(int a, Sym *s, Node *n)
1333
{
1334
 
1335
	nextpc();
1336
	p->as = a;
1337
	p->from.type = D_OREG;
1338
	p->from.sym = s;
1339
	if(a == ATEXT)
1340
		p->reg = (profileflg ? 0 : NOPROF);
1341
	p->from.name = D_EXTERN;
1342
	if(s->class == CSTATIC)
1343
		p->from.name = D_STATIC;
1344
	naddr(n, &p->to);
1345
	if(a == ADATA || a == AGLOBL)
1346
		pc--;
1347
}
1348
 
1349
int
1350
sconst(Node *n)
1351
{
1352
	vlong vv;
1353
 
1354
	if(n->op == OCONST) {
1355
		if(!typefd[n->type->etype]) {
1356
			vv = n->vconst;
1357
			if(vv >= (vlong)(-32766) && vv < (vlong)32766)
1358
				return 1;
1359
		}
1360
	}
1361
	return 0;
1362
}
1363
 
1364
int
1365
sval(long v)
1366
{
1367
	if(v >= -32766L && v < 32766L)
1368
		return 1;
1369
	return 0;
1370
}
1371
 
1372
long
1373
exreg(Type *t)
1374
{
1375
	long o;
1376
 
1377
	if(typechlp[t->etype]) {
1378
		if(exregoffset <= 16)
1379
			return 0;
1380
		o = exregoffset;
1381
		exregoffset--;
1382
		return o;
1383
	}
1384
	if(typefd[t->etype]) {
1385
		if(exfregoffset <= 16)
1386
			return 0;
1387
		o = exfregoffset + NREG;
1388
		exfregoffset--;
1389
		return o;
1390
	}
1391
	return 0;
1392
}
1393
 
1394
schar	ewidth[NTYPE] =
1395
{
1396
	-1,		/* [TXXX] */
1397
	SZ_CHAR,	/* [TCHAR] */
1398
	SZ_CHAR,	/* [TUCHAR] */
1399
	SZ_SHORT,	/* [TSHORT] */
1400
	SZ_SHORT,	/* [TUSHORT] */
1401
	SZ_INT,		/* [TINT] */
1402
	SZ_INT,		/* [TUINT] */
1403
	SZ_LONG,	/* [TLONG] */
1404
	SZ_LONG,	/* [TULONG] */
1405
	SZ_VLONG,	/* [TVLONG] */
1406
	SZ_VLONG,	/* [TUVLONG] */
1407
	SZ_FLOAT,	/* [TFLOAT] */
1408
	SZ_DOUBLE,	/* [TDOUBLE] */
1409
	SZ_IND,		/* [TIND] */
1410
	0,		/* [TFUNC] */
1411
	-1,		/* [TARRAY] */
1412
	0,		/* [TVOID] */
1413
	-1,		/* [TSTRUCT] */
1414
	-1,		/* [TUNION] */
1415
	SZ_INT,		/* [TENUM] */
1416
};
1417
 
1418
long	ncast[NTYPE] =
1419
{
1420
	0,				/* [TXXX] */
1421
	BCHAR|BUCHAR,			/* [TCHAR] */
1422
	BCHAR|BUCHAR,			/* [TUCHAR] */
1423
	BSHORT|BUSHORT,			/* [TSHORT] */
1424
	BSHORT|BUSHORT,			/* [TUSHORT] */
1425
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1426
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1427
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1428
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1429
	BVLONG|BUVLONG,			/* [TVLONG] */
1430
	BVLONG|BUVLONG,			/* [TUVLONG] */
1431
	BFLOAT,				/* [TFLOAT] */
1432
	BDOUBLE,			/* [TDOUBLE] */
1433
	BLONG|BULONG|BIND,		/* [TIND] */
1434
	0,				/* [TFUNC] */
1435
	0,				/* [TARRAY] */
1436
	0,				/* [TVOID] */
1437
	BSTRUCT,			/* [TSTRUCT] */
1438
	BUNION,				/* [TUNION] */
1439
	0,				/* [TENUM] */
1440
};