Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/cmd/5c/txt.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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