Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "gc.h"
2
 
3
static	int	resvreg[nelem(reg)];
4
 
5
static	void	gopcode64(int, Node*, Node*, Node*);
6
static	void	gori64(int, Node*, Node*, Node*);
7
static	void	gandi64(int, Node*, Node*, Node*);
8
 
9
void
10
ginit(void)
11
{
12
	Type *t;
13
 
14
	thechar = 'q';
15
	thestring = "power";
16
	exregoffset = REGEXT;
17
	exfregoffset = FREGEXT;
18
	newvlongcode = 1;
19
	listinit();
20
	nstring = 0;
21
	mnstring = 0;
22
	nrathole = 0;
23
	pc = 0;
24
	breakpc = -1;
25
	continpc = -1;
26
	cases = C;
27
	firstp = P;
28
	lastp = P;
29
	tfield = types[TLONG];
30
 
31
	typeswitch = typechlv;
32
 
33
	zprog.link = P;
34
	zprog.as = AGOK;
35
	zprog.reg = NREG;
36
	zprog.from.type = D_NONE;
37
	zprog.from.name = D_NONE;
38
	zprog.from.reg = NREG;
39
	zprog.from3 = zprog.from;
40
	zprog.to = zprog.from;
41
 
42
	regnode.op = OREGISTER;
43
	regnode.class = CEXREG;
44
	regnode.reg = 0;
45
	regnode.complex = 0;
46
	regnode.addable = 11;
47
	regnode.type = types[TLONG];
48
 
49
	constnode.op = OCONST;
50
	constnode.class = CXXX;
51
	constnode.complex = 0;
52
	constnode.addable = 20;
53
	constnode.type = types[TLONG];
54
 
55
	fconstnode.op = OCONST;
56
	fconstnode.class = CXXX;
57
	fconstnode.complex = 0;
58
	fconstnode.addable = 20;
59
	fconstnode.type = types[TDOUBLE];
60
 
61
	nodsafe = new(ONAME, Z, Z);
62
	nodsafe->sym = slookup(".safe");
63
	nodsafe->type = types[TINT];
64
	nodsafe->etype = types[TINT]->etype;
65
	nodsafe->class = CAUTO;
66
	complex(nodsafe);
67
 
68
	t = typ(TARRAY, types[TCHAR]);
69
	symrathole = slookup(".rathole");
70
	symrathole->class = CGLOBL;
71
	symrathole->type = t;
72
 
73
	nodrat = new(ONAME, Z, Z);
74
	nodrat->sym = symrathole;
75
	nodrat->type = types[TIND];
76
	nodrat->etype = TVOID;
77
	nodrat->class = CGLOBL;
78
	complex(nodrat);
79
	nodrat->type = t;
80
 
81
	com64init();
82
 
83
	memset(reg, 0, sizeof(reg));
84
	reg[REGZERO] = 1;	/* don't use */
85
	reg[REGTMP] = 1;
86
	reg[FREGCVI+NREG] = 1;
87
	reg[FREGZERO+NREG] = 1;
88
	reg[FREGHALF+NREG] = 1;
89
	reg[FREGONE+NREG] = 1;
90
	reg[FREGTWO+NREG] = 1;
91
	memmove(resvreg, reg, sizeof(reg));
92
}
93
 
94
void
95
gclean(void)
96
{
97
	int i;
98
	Sym *s;
99
 
100
	for(i=0; i<NREG; i++)
101
		if(reg[i] && !resvreg[i])
102
			diag(Z, "reg %d left allocated", i);
103
	for(i=NREG; i<NREG+NREG; i++)
104
		if(reg[i] && !resvreg[i])
105
			diag(Z, "freg %d left allocated", i-NREG);
106
	while(mnstring)
107
		outstring("", 1L);
108
	symstring->type->width = nstring;
109
	symrathole->type->width = nrathole;
110
	for(i=0; i<NHASH; i++)
111
	for(s = hash[i]; s != S; s = s->link) {
112
		if(s->type == T)
113
			continue;
114
		if(s->type->width == 0)
115
			continue;
116
		if(s->class != CGLOBL && s->class != CSTATIC)
117
			continue;
118
		if(s->type == types[TENUM])
119
			continue;
120
		gpseudo(AGLOBL, s, nodconst(s->type->width));
121
	}
122
	nextpc();
123
	p->as = AEND;
124
	outcode();
125
}
126
 
127
void
128
nextpc(void)
129
{
130
 
131
	p = alloc(sizeof(*p));
132
	*p = zprog;
133
	p->lineno = nearln;
134
	pc++;
135
	if(firstp == P) {
136
		firstp = p;
137
		lastp = p;
138
		return;
139
	}
140
	lastp->link = p;
141
	lastp = p;
142
}
143
 
144
void
145
gargs(Node *n, Node *tn1, Node *tn2)
146
{
147
	long regs;
148
	Node fnxargs[20], *fnxp;
149
 
150
	regs = cursafe;
151
 
152
	fnxp = fnxargs;
153
	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
154
 
155
	curarg = 0;
156
	fnxp = fnxargs;
157
	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
158
 
159
	cursafe = regs;
160
}
161
 
162
void
163
garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
164
{
165
	Node nod;
166
 
167
	if(n == Z)
168
		return;
169
	if(n->op == OLIST) {
170
		garg1(n->left, tn1, tn2, f, fnxp);
171
		garg1(n->right, tn1, tn2, f, fnxp);
172
		return;
173
	}
174
	if(f == 0) {
175
		if(n->complex >= FNX) {
176
			regsalloc(*fnxp, n);
177
			nod = znode;
178
			nod.op = OAS;
179
			nod.left = *fnxp;
180
			nod.right = n;
181
			nod.type = n->type;
182
			cgen(&nod, Z);
183
			(*fnxp)++;
184
		}
185
		return;
186
	}
187
	if(typesuv[n->type->etype]) {
188
		regaalloc(tn2, n);
189
		if(n->complex >= FNX) {
190
			cgen(*fnxp, tn2);
191
			(*fnxp)++;
192
		} else
193
			cgen(n, tn2);
194
		return;
195
	}
196
	if(REGARG && curarg == 0 && typechlp[n->type->etype]) {
197
		regaalloc1(tn1, n);
198
		if(n->complex >= FNX) {
199
			cgen(*fnxp, tn1);
200
			(*fnxp)++;
201
		} else
202
			cgen(n, tn1);
203
		return;
204
	}
205
	if(vconst(n) == 0) {
206
		regaalloc(tn2, n);
207
		gopcode(OAS, n, Z, tn2);
208
		return;
209
	}
210
	regalloc(tn1, n, Z);
211
	if(n->complex >= FNX) {
212
		cgen(*fnxp, tn1);
213
		(*fnxp)++;
214
	} else
215
		cgen(n, tn1);
216
	regaalloc(tn2, n);
217
	gopcode(OAS, tn1, Z, tn2);
218
	regfree(tn1);
219
}
220
 
221
Node*
222
nod32const(vlong v)
223
{
224
	constnode.vconst = v & MASK(32);
225
	return &constnode;
226
}
227
 
228
Node*
229
nodconst(long v)
230
{
231
	constnode.vconst = v;
232
	return &constnode;
233
}
234
 
235
Node*
236
nodfconst(double d)
237
{
238
	fconstnode.fconst = d;
239
	return &fconstnode;
240
}
241
 
242
void
243
nodreg(Node *n, Node *nn, int reg)
244
{
245
	*n = regnode;
246
	n->reg = reg;
247
	n->type = nn->type;
248
	n->lineno = nn->lineno;
249
}
250
 
251
void
252
regret(Node *n, Node *nn)
253
{
254
	int r;
255
 
256
	r = REGRET;
257
	if(typefd[nn->type->etype])
258
		r = FREGRET+NREG;
259
	nodreg(n, nn, r);
260
	reg[r]++;
261
}
262
 
263
void
264
regalloc(Node *n, Node *tn, Node *o)
265
{
266
	int i, j;
267
	static int lasti;
268
 
269
	switch(tn->type->etype) {
270
	case TCHAR:
271
	case TUCHAR:
272
	case TSHORT:
273
	case TUSHORT:
274
	case TINT:
275
	case TUINT:
276
	case TLONG:
277
	case TULONG:
278
	case TIND:
279
		if(o != Z && o->op == OREGISTER) {
280
			i = o->reg;
281
			if(i > 0 && i < NREG)
282
				goto out;
283
		}
284
		j = lasti + REGRET+1;
285
		for(i=REGRET+1; i<NREG; i++) {
286
			if(j >= NREG)
287
				j = REGRET+1;
288
			if(reg[j] == 0) {
289
				i = j;
290
				goto out;
291
			}
292
			j++;
293
		}
294
		diag(tn, "out of fixed registers");
295
		goto err;
296
 
297
	case TFLOAT:
298
	case TDOUBLE:
299
		if(o != Z && o->op == OREGISTER) {
300
			i = o->reg;
301
			if(i >= NREG && i < NREG+NREG)
302
				goto out;
303
		}
304
		j = lasti + NREG;
305
		for(i=NREG; i<NREG+NREG; i++) {
306
			if(j >= NREG+NREG)
307
				j = NREG;
308
			if(reg[j] == 0) {
309
				i = j;
310
				goto out;
311
			}
312
			j++;
313
		}
314
		diag(tn, "out of float registers");
315
		goto err;
316
 
317
	case TVLONG:
318
	case TUVLONG:
319
		n->op = OREGPAIR;
320
		n->complex = 0;	/* already in registers */
321
		n->addable = 11;
322
		n->type = tn->type;
323
		n->lineno = nearln;
324
		n->left = alloc(sizeof(Node));
325
		n->right = alloc(sizeof(Node));
326
		if(o != Z && o->op == OREGPAIR) {
327
			regalloc(n->left, &regnode, o->left);
328
			regalloc(n->right, &regnode, o->right);
329
		} else {
330
			regalloc(n->left, &regnode, Z);
331
			regalloc(n->right, &regnode, Z);
332
		}
333
		n->right->type = types[TULONG];
334
		if(tn->type->etype == TUVLONG)
335
			n->left->type = types[TULONG];	/* TO DO: is this a bad idea? */
336
		return;
337
	}
338
	diag(tn, "unknown type in regalloc: %T", tn->type);
339
err:
340
	i = 0;
341
out:
342
	if(i)
343
		reg[i]++;
344
	lasti++;
345
	if(lasti >= 5)
346
		lasti = 0;
347
	nodreg(n, tn, i);
348
}
349
 
350
void
351
regialloc(Node *n, Node *tn, Node *o)
352
{
353
	Node nod;
354
 
355
	nod = *tn;
356
	nod.type = types[TIND];
357
	regalloc(n, &nod, o);
358
}
359
 
360
void
361
regfree(Node *n)
362
{
363
	int i;
364
 
365
	if(n->op == OREGPAIR) {
366
		regfree(n->left);
367
		regfree(n->right);
368
		return;
369
	}
370
	i = 0;
371
	if(n->op != OREGISTER && n->op != OINDREG)
372
		goto err;
373
	i = n->reg;
374
	if(i < 0 || i >= sizeof(reg))
375
		goto err;
376
	if(reg[i] <= 0)
377
		goto err;
378
	reg[i]--;
379
	return;
380
err:
381
	diag(n, "error in regfree: %d [%d]", i, reg[i]);
382
	prtree(n, "regfree");
383
}
384
 
385
void
386
regsalloc(Node *n, Node *nn)
387
{
388
	cursafe = align(cursafe+stkoff, nn->type, Aaut3)-stkoff;
389
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
390
//	if(nn->type->etype == TDOUBLE || nn->type->etype == TVLONG){
391
//		extern int hasdoubled;
392
//		fprint(2, "stkoff=%ld cursafe=%ld curarg=%ld %d\n", stkoff, cursafe, curarg, hasdoubled);
393
//	}
394
	*n = *nodsafe;
395
	n->xoffset = -(stkoff + cursafe);
396
	n->type = nn->type;
397
	n->etype = nn->type->etype;
398
	n->lineno = nn->lineno;
399
}
400
 
401
void
402
regaalloc1(Node *n, Node *nn)
403
{
404
	nodreg(n, nn, REGARG);
405
	reg[REGARG]++;
406
	curarg = align(curarg, nn->type, Aarg1);
407
	curarg = align(curarg, nn->type, Aarg2);
408
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
409
}
410
 
411
void
412
regaalloc(Node *n, Node *nn)
413
{
414
	curarg = align(curarg, nn->type, Aarg1);
415
	*n = *nn;
416
	n->op = OINDREG;
417
	n->reg = REGSP;
418
	n->xoffset = curarg + SZ_LONG;
419
	n->complex = 0;
420
	n->addable = 20;
421
	curarg = align(curarg, nn->type, Aarg2);
422
	maxargsafe = maxround(maxargsafe, cursafe+curarg);
423
}
424
 
425
void
426
regind(Node *n, Node *nn)
427
{
428
 
429
	if(n->op != OREGISTER) {
430
		diag(n, "regind not OREGISTER");
431
		return;
432
	}
433
	n->op = OINDREG;
434
	n->type = nn->type;
435
}
436
 
437
void
438
raddr(Node *n, Prog *p)
439
{
440
	Adr a;
441
 
442
	naddr(n, &a);
443
	if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
444
		a.type = D_REG;
445
		a.reg = REGZERO;
446
	}
447
	if(a.type != D_REG && a.type != D_FREG) {
448
		if(n)
449
			diag(n, "bad in raddr: %O", n->op);
450
		else
451
			diag(n, "bad in raddr: <null>");
452
		p->reg = NREG;
453
	} else
454
		p->reg = a.reg;
455
}
456
 
457
void
458
naddr(Node *n, Adr *a)
459
{
460
	long v;
461
 
462
	a->type = D_NONE;
463
	if(n == Z)
464
		return;
465
	switch(n->op) {
466
	default:
467
	bad:
468
		diag(n, "bad in naddr: %O", n->op);
469
		break;
470
 
471
	case OREGISTER:
472
		a->type = D_REG;
473
		a->sym = S;
474
		a->reg = n->reg;
475
		if(a->reg >= NREG) {
476
			a->type = D_FREG;
477
			a->reg -= NREG;
478
		}
479
		break;
480
 
481
	case OIND:
482
		naddr(n->left, a);
483
		a->offset += n->xoffset;	/* little hack for reglcgenv */
484
		if(a->type == D_REG) {
485
			a->type = D_OREG;
486
			break;
487
		}
488
		if(a->type == D_CONST) {
489
			a->type = D_OREG;
490
			break;
491
		}
492
		goto bad;
493
 
494
	case OINDREG:
495
		a->type = D_OREG;
496
		a->sym = S;
497
		a->offset = n->xoffset;
498
		a->reg = n->reg;
499
		break;
500
 
501
	case ONAME:
502
		a->etype = n->etype;
503
		a->type = D_OREG;
504
		a->name = D_STATIC;
505
		a->sym = n->sym;
506
		a->offset = n->xoffset;
507
		if(n->class == CSTATIC)
508
			break;
509
		if(n->class == CEXTERN || n->class == CGLOBL) {
510
			a->name = D_EXTERN;
511
			break;
512
		}
513
		if(n->class == CAUTO) {
514
			a->name = D_AUTO;
515
			break;
516
		}
517
		if(n->class == CPARAM) {
518
			a->name = D_PARAM;
519
			break;
520
		}
521
		goto bad;
522
 
523
	case OCONST:
524
		a->sym = S;
525
		a->reg = NREG;
526
		if(typefd[n->type->etype]) {
527
			a->type = D_FCONST;
528
			a->dval = n->fconst;
529
		} else {
530
			a->type = D_CONST;
531
			a->offset = n->vconst;
532
		}
533
		break;
534
 
535
	case OADDR:
536
		naddr(n->left, a);
537
		if(a->type == D_OREG) {
538
			a->type = D_CONST;
539
			break;
540
		}
541
		goto bad;
542
 
543
	case OADD:
544
		if(n->left->op == OCONST) {
545
			naddr(n->left, a);
546
			v = a->offset;
547
			naddr(n->right, a);
548
		} else {
549
			naddr(n->right, a);
550
			v = a->offset;
551
			naddr(n->left, a);
552
		}
553
		a->offset += v;
554
		break;
555
 
556
	}
557
}
558
 
559
void
560
gloadhi(Node *f, Node *t, int c)
561
{
562
	Type *ot;
563
 
564
	if(f->op == OCONST){
565
		f = nodconst((long)(f->vconst>>32));
566
		if(c==1 && sconst(f) || c==2 && uconst(f)){
567
			if(t->op == OREGISTER)
568
				regfree(t);
569
			*t = *f;
570
			return;
571
		}
572
	}
573
	if(f->op == OREGPAIR) {
574
		gmove(f->left, t);
575
		return;
576
	}
577
	ot = f->type;
578
	f->type = types[TLONG];
579
	gmove(f, t);
580
	f->type = ot;
581
}
582
 
583
void
584
gloadlo(Node *f, Node *t, int c)
585
{
586
	Type *ot;
587
 
588
	if(f->op == OCONST){
589
		f = nodconst((long)f->vconst);
590
		if(c && uconst(f)){
591
			if(t->op == OREGISTER)
592
				regfree(t);
593
			*t = *f;
594
			return;
595
		}
596
	}
597
	if(f->op == OREGPAIR) {
598
		gmove(f->right, t);
599
		return;
600
	}
601
	ot = f->type;
602
	f->type = types[TLONG];
603
	f->xoffset += SZ_LONG;
604
	if(0){
605
		prtree(f, "gloadlo f"); prtree(t, "gloadlo t");
606
	}
607
	gmove(f, t);
608
	f->xoffset -= SZ_LONG;
609
	f->type = ot;
610
}
611
 
612
void
613
fop(int as, int f1, int f2, Node *t)
614
{
615
	Node nod1, nod2, nod3;
616
 
617
	nodreg(&nod1, t, NREG+f1);
618
	nodreg(&nod2, t, NREG+f2);
619
	regalloc(&nod3, t, t);
620
	gopcode(as, &nod1, &nod2, &nod3);
621
	gmove(&nod3, t);
622
	regfree(&nod3);
623
}
624
 
625
void
626
gmove(Node *f, Node *t)
627
{
628
	int ft, tt, a;
629
	Node nod, fxc0, fxc1, fxc2, fxrat;
630
	Prog *p1;
631
	double d;
632
 
633
	ft = f->type->etype;
634
	tt = t->type->etype;
635
 
636
	if(ft == TDOUBLE && f->op == OCONST) {
637
		d = f->fconst;
638
		if(d == 0.0) {
639
			a = FREGZERO;
640
			goto ffreg;
641
		}
642
		if(d == 0.5) {
643
			a = FREGHALF;
644
			goto ffreg;
645
		}
646
		if(d == 1.0) {
647
			a = FREGONE;
648
			goto ffreg;
649
		}
650
		if(d == 2.0) {
651
			a = FREGTWO;
652
			goto ffreg;
653
		}
654
		if(d == -.5) {
655
			fop(OSUB, FREGHALF, FREGZERO, t);
656
			return;
657
		}
658
		if(d == -1.0) {
659
			fop(OSUB, FREGONE, FREGZERO, t);
660
			return;
661
		}
662
		if(d == -2.0) {
663
			fop(OSUB, FREGTWO, FREGZERO, t);
664
			return;
665
		}
666
		if(d == 1.5) {
667
			fop(OADD, FREGONE, FREGHALF, t);
668
			return;
669
		}
670
		if(d == 2.5) {
671
			fop(OADD, FREGTWO, FREGHALF, t);
672
			return;
673
		}
674
		if(d == 3.0) {
675
			fop(OADD, FREGTWO, FREGONE, t);
676
			return;
677
		}
678
	}
679
	if(ft == TFLOAT && f->op == OCONST) {
680
		d = f->fconst;
681
		if(d == 0) {
682
			a = FREGZERO;
683
		ffreg:
684
			nodreg(&nod, f, NREG+a);
685
			gmove(&nod, t);
686
			return;
687
		}
688
	}
689
	if((ft == TVLONG || ft == TUVLONG) && f->op == OCONST && t->op == OREGPAIR) {
690
		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
691
			gmove(nod32const(f->vconst>>32), t->left);
692
		else
693
			gmove(nod32const(f->vconst), t->left);
694
		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
695
			gmove(nod32const(f->vconst), t->right);
696
		else
697
			gmove(nod32const(f->vconst>>32), t->right);
698
		return;
699
	}
700
	/*
701
	 * a load --
702
	 * put it into a register then
703
	 * worry what to do with it.
704
	 */
705
	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
706
		switch(ft) {
707
		default:
708
			a = AMOVW;
709
			break;
710
		case TFLOAT:
711
			a = AFMOVS;
712
			break;
713
		case TDOUBLE:
714
			a = AFMOVD;
715
			break;
716
		case TCHAR:
717
			a = AMOVB;
718
			break;
719
		case TUCHAR:
720
			a = AMOVBZ;
721
			break;
722
		case TSHORT:
723
			a = AMOVH;
724
			break;
725
		case TUSHORT:
726
			a = AMOVHZ;
727
			break;
728
		}
729
		if(typev[ft]) {
730
			if(typev[tt]) {
731
				regalloc(&nod, f, t);
732
				/* low order first, because its value will be used first */
733
				f->xoffset += SZ_LONG;
734
				gins(AMOVW, f, nod.right);
735
				f->xoffset -= SZ_LONG;
736
				gins(AMOVW, f, nod.left);
737
			} else {
738
				/* assumed not float or double */
739
				regalloc(&nod, &regnode, t);
740
				f->xoffset += SZ_LONG;
741
				gins(AMOVW, f, &nod);
742
				f->xoffset -= SZ_LONG;
743
			}
744
		} else {
745
			regalloc(&nod, f, t);
746
			gins(a, f, &nod);
747
		}
748
		gmove(&nod, t);
749
		regfree(&nod);
750
		return;
751
	}
752
 
753
	/*
754
	 * a store --
755
	 * put it into a register then
756
	 * store it.
757
	 */
758
	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
759
		switch(tt) {
760
		default:
761
			a = AMOVW;
762
			break;
763
		case TUCHAR:
764
			a = AMOVBZ;
765
			break;
766
		case TCHAR:
767
			a = AMOVB;
768
			break;
769
		case TUSHORT:
770
			a = AMOVHZ;
771
			break;
772
		case TSHORT:
773
			a = AMOVH;
774
			break;
775
		case TFLOAT:
776
			a = AFMOVS;
777
			break;
778
		case TDOUBLE:
779
			a = AFMOVD;
780
			break;
781
		}
782
		if(R0ISZERO && !typefd[ft] && vconst(f) == 0) {
783
			gins(a, f, t);
784
			if(typev[tt]) {
785
				t->xoffset += SZ_LONG;
786
				gins(a, f, t);
787
				t->xoffset -= SZ_LONG;
788
			}
789
			return;
790
		}
791
		if(ft == tt)
792
			regalloc(&nod, t, f);
793
		else
794
			regalloc(&nod, t, Z);
795
		gmove(f, &nod);
796
		if(typev[tt]) {
797
			t->xoffset += SZ_LONG;
798
			gins(a, nod.right, t);
799
			t->xoffset -= SZ_LONG;
800
			gins(a, nod.left, t);
801
		} else
802
			gins(a, &nod, t);
803
		regfree(&nod);
804
		return;
805
	}
806
 
807
	/*
808
	 * type x type cross table
809
	 */
810
	a = AGOK;
811
	switch(ft) {
812
	case TDOUBLE:
813
	case TFLOAT:
814
		switch(tt) {
815
		case TDOUBLE:
816
			a = AFMOVD;
817
			if(ft == TFLOAT)
818
				a = AFMOVS;	/* AFMOVSD */
819
			break;
820
		case TFLOAT:
821
			a = AFRSP;
822
			if(ft == TFLOAT)
823
				a = AFMOVS;
824
			break;
825
		case TINT:
826
		case TUINT:
827
		case TLONG:
828
		case TULONG:
829
		case TIND:
830
		case TSHORT:
831
		case TUSHORT:
832
		case TCHAR:
833
		case TUCHAR:
834
			/* BUG: not right for unsigned long */
835
			regalloc(&nod, f, Z);	/* should be type float */
836
			regsalloc(&fxrat, &fconstnode);
837
			gins(AFCTIWZ, f, &nod);
838
			gins(AFMOVD, &nod, &fxrat);
839
			regfree(&nod);
840
			fxrat.type = nodrat->type;
841
			fxrat.etype = nodrat->etype;
842
			fxrat.xoffset += 4;
843
			gins(AMOVW, &fxrat, t);
844
			gmove(t, t);
845
			return;
846
		}
847
		break;
848
	case TINT:
849
	case TUINT:
850
	case TLONG:
851
	case TULONG:
852
	case TIND:
853
		switch(tt) {
854
		case TDOUBLE:
855
		case TFLOAT:
856
			goto fxtofl;
857
		case TINT:
858
		case TUINT:
859
		case TLONG:
860
		case TULONG:
861
		case TIND:
862
		case TSHORT:
863
		case TUSHORT:
864
		case TCHAR:
865
		case TUCHAR:
866
			a = AMOVW;
867
			break;
868
		}
869
		break;
870
	case TSHORT:
871
		switch(tt) {
872
		case TDOUBLE:
873
		case TFLOAT:
874
			goto fxtofl;
875
		case TINT:
876
		case TUINT:
877
		case TLONG:
878
		case TULONG:
879
		case TIND:
880
			a = AMOVH;
881
			break;
882
		case TSHORT:
883
		case TUSHORT:
884
		case TCHAR:
885
		case TUCHAR:
886
			a = AMOVW;
887
			break;
888
		}
889
		break;
890
	case TUSHORT:
891
		switch(tt) {
892
		case TDOUBLE:
893
		case TFLOAT:
894
			goto fxtofl;
895
		case TINT:
896
		case TUINT:
897
		case TLONG:
898
		case TULONG:
899
		case TIND:
900
			a = AMOVHZ;
901
			break;
902
		case TSHORT:
903
		case TUSHORT:
904
		case TCHAR:
905
		case TUCHAR:
906
			a = AMOVW;
907
			break;
908
		}
909
		break;
910
	case TCHAR:
911
		switch(tt) {
912
		case TDOUBLE:
913
		case TFLOAT:
914
			goto fxtofl;
915
		case TINT:
916
		case TUINT:
917
		case TLONG:
918
		case TULONG:
919
		case TIND:
920
		case TSHORT:
921
		case TUSHORT:
922
			a = AMOVB;
923
			break;
924
		case TCHAR:
925
		case TUCHAR:
926
			a = AMOVW;
927
			break;
928
		}
929
		break;
930
	case TUCHAR:
931
		switch(tt) {
932
		case TDOUBLE:
933
		case TFLOAT:
934
		fxtofl:
935
			/*
936
			 * rat[0] = 0x43300000; rat[1] = f^0x80000000;
937
			 * t = *(double*)rat - FREGCVI;
938
			 * is-unsigned(t) => if(t<0) t += 2^32;
939
			 * could be streamlined for int-to-float
940
			 */
941
			regalloc(&fxc0, f, Z);
942
			regalloc(&fxc2, f, Z);
943
			regsalloc(&fxrat, &fconstnode);	/* should be type float */
944
			gins(AMOVW, nodconst(0x43300000L), &fxc0);
945
			gins(AMOVW, f, &fxc2);
946
			gins(AMOVW, &fxc0, &fxrat);
947
			gins(AXOR, nodconst(0x80000000L), &fxc2);
948
			fxc1 = fxrat;
949
			fxc1.type = nodrat->type;
950
			fxc1.etype = nodrat->etype;
951
			fxc1.xoffset += SZ_LONG;
952
			gins(AMOVW, &fxc2, &fxc1);
953
			regfree(&fxc2);
954
			regfree(&fxc0);
955
			regalloc(&nod, t, t);	/* should be type float */
956
			gins(AFMOVD, &fxrat, &nod);
957
			nodreg(&fxc1, t, NREG+FREGCVI);
958
			gins(AFSUB, &fxc1, &nod);
959
			a = AFMOVD;
960
			if(tt == TFLOAT)
961
				a = AFRSP;
962
			gins(a, &nod, t);
963
			regfree(&nod);
964
			if(ft == TULONG) {
965
				regalloc(&nod, t, Z);
966
				if(tt == TFLOAT) {
967
					gins(AFCMPU, t, Z);
968
					p->to.type = D_FREG;
969
					p->to.reg = FREGZERO;
970
					gins(ABGE, Z, Z);
971
					p1 = p;
972
					gins(AFMOVS, nodfconst(4294967296.), &nod);
973
					gins(AFADDS, &nod, t);
974
				} else {
975
					gins(AFCMPU, t, Z);
976
					p->to.type = D_FREG;
977
					p->to.reg = FREGZERO;
978
					gins(ABGE, Z, Z);
979
					p1 = p;
980
					gins(AFMOVD, nodfconst(4294967296.), &nod);
981
					gins(AFADD, &nod, t);
982
				}
983
				patch(p1, pc);
984
				regfree(&nod);
985
			}
986
			return;
987
		case TINT:
988
		case TUINT:
989
		case TLONG:
990
		case TULONG:
991
		case TIND:
992
		case TSHORT:
993
		case TUSHORT:
994
			a = AMOVBZ;
995
			break;
996
		case TCHAR:
997
		case TUCHAR:
998
			a = AMOVW;
999
			break;
1000
		}
1001
		break;
1002
	case TVLONG:
1003
	case TUVLONG:
1004
		switch(tt) {
1005
		case TVLONG:
1006
		case TUVLONG:
1007
			a = AMOVW;
1008
			break;
1009
		}
1010
		break;
1011
	}
1012
	if(a == AGOK)
1013
		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
1014
	if(a == AMOVW || a == AFMOVS || a == AFMOVD)
1015
	if(samaddr(f, t))
1016
		return;
1017
	if(typev[ft]) {
1018
		if(f->op != OREGPAIR || t->op != OREGPAIR)
1019
			diag(Z, "bad vlong in gmove (%O->%O)", f->op, t->op);
1020
		gins(a, f->left, t->left);
1021
		gins(a, f->right, t->right);
1022
	} else
1023
		gins(a, f, t);
1024
}
1025
 
1026
void
1027
gins(int a, Node *f, Node *t)
1028
{
1029
 
1030
	nextpc();
1031
	p->as = a;
1032
	if(f != Z)
1033
		naddr(f, &p->from);
1034
	if(t != Z)
1035
		naddr(t, &p->to);
1036
	if(debug['g'])
1037
		print("%P\n", p);
1038
}
1039
 
1040
void
1041
gins3(int a, Node *f1, Node *f2, Node *t)
1042
{
1043
	Adr ta;
1044
 
1045
	nextpc();
1046
	p->as = a;
1047
	if(f1 != Z)
1048
		naddr(f1, &p->from);
1049
	if(f2 != Z && (f2->op != OREGISTER || !samaddr(f2, t))) {
1050
		ta = zprog.from;	/* TO DO */
1051
		naddr(f2, &ta);
1052
		p->reg = ta.reg;
1053
		if(ta.type == D_CONST && ta.offset == 0) {
1054
			if(R0ISZERO)
1055
				p->reg = REGZERO;
1056
			else
1057
				diag(Z, "REGZERO in gins3 %A", a);
1058
		}else if(ta.type == D_CONST)
1059
			p->from3 = ta;
1060
	}
1061
	if(t != Z)
1062
		naddr(t, &p->to);
1063
	if(debug['g'])
1064
		print("%P\n", p);
1065
}
1066
 
1067
void
1068
gins4(int a, Node *f1, Node *f2, Node *f3, Node *t)
1069
{
1070
	Adr ta;
1071
 
1072
	nextpc();
1073
	p->as = a;
1074
	naddr(f1, &p->from);
1075
	if(f2->op != OREGISTER && (f2->op != OCONST || vconst(f2) != 0))
1076
		diag(f2, "invalid gins4");
1077
	naddr(f2, &ta);
1078
	p->reg = ta.reg;
1079
	if(ta.type == D_CONST && ta.offset == 0)
1080
		p->reg = REGZERO;
1081
	naddr(f3, &p->from3);
1082
	naddr(t, &p->to);
1083
	if(debug['g'])
1084
		print("%P\n", p);
1085
}
1086
 
1087
void
1088
gopcode(int o, Node *f1, Node *f2, Node *t)
1089
{
1090
	int a, et, uns;
1091
 
1092
	if(o == OAS) {
1093
		gmove(f1, t);
1094
		return;
1095
	}
1096
	et = TLONG;
1097
	if(f1 != Z && f1->type != T) {
1098
		if(f1->op == OCONST && t != Z && t->type != T)
1099
			et = t->type->etype;
1100
		else
1101
			et = f1->type->etype;
1102
	}
1103
	if((typev[et] || t->type != T && typev[t->type->etype]) && o != OFUNC) {
1104
		gopcode64(o, f1, f2, t);
1105
		return;
1106
	}
1107
	uns = 0;
1108
	a = AGOK;
1109
	switch(o) {
1110
 
1111
	case OASADD:
1112
	case OADD:
1113
		a = AADD;
1114
		if(et == TFLOAT)
1115
			a = AFADDS;
1116
		else
1117
		if(et == TDOUBLE)
1118
			a = AFADD;
1119
		break;
1120
 
1121
	case OASSUB:
1122
	case OSUB:
1123
		a = ASUB;
1124
		if(et == TFLOAT)
1125
			a = AFSUBS;
1126
		else
1127
		if(et == TDOUBLE)
1128
			a = AFSUB;
1129
		break;
1130
 
1131
	case OASOR:
1132
	case OOR:
1133
		a = AOR;
1134
		break;
1135
 
1136
	case OASAND:
1137
	case OAND:
1138
		a = AAND;
1139
		if(f1->op == OCONST)
1140
			a = AANDCC;
1141
		break;
1142
 
1143
	case OASXOR:
1144
	case OXOR:
1145
		a = AXOR;
1146
		break;
1147
 
1148
	case OASLSHR:
1149
	case OLSHR:
1150
		a = ASRW;
1151
		break;
1152
 
1153
	case OASASHR:
1154
	case OASHR:
1155
		a = ASRAW;
1156
		break;
1157
 
1158
	case OASASHL:
1159
	case OASHL:
1160
		a = ASLW;
1161
		break;
1162
 
1163
	case OFUNC:
1164
		a = ABL;
1165
		break;
1166
 
1167
	case OASLMUL:
1168
	case OLMUL:
1169
	case OASMUL:
1170
	case OMUL:
1171
		if(et == TFLOAT) {
1172
			a = AFMULS;
1173
			break;
1174
		} else
1175
		if(et == TDOUBLE) {
1176
			a = AFMUL;
1177
			break;
1178
		}
1179
		a = AMULLW;
1180
		break;
1181
 
1182
	case OASDIV:
1183
	case ODIV:
1184
		if(et == TFLOAT) {
1185
			a = AFDIVS;
1186
			break;
1187
		} else
1188
		if(et == TDOUBLE) {
1189
			a = AFDIV;
1190
			break;
1191
		}
1192
		a = ADIVW;
1193
		break;
1194
 
1195
	case OASMOD:
1196
	case OMOD:
1197
		a = AREM;
1198
		break;
1199
 
1200
	case OASLMOD:
1201
	case OLMOD:
1202
		a = AREMU;
1203
		break;
1204
 
1205
	case OASLDIV:
1206
	case OLDIV:
1207
		a = ADIVWU;
1208
		break;
1209
 
1210
	case OCOM:
1211
		a = ANOR;
1212
		break;
1213
 
1214
	case ONEG:
1215
		a = ANEG;
1216
		if(et == TFLOAT || et == TDOUBLE)
1217
			a = AFNEG;
1218
		break;
1219
 
1220
	case OEQ:
1221
		a = ABEQ;
1222
		if(t->op == OCONST && t->vconst >= (1<<15))
1223
			goto cmpu;
1224
		goto cmp;
1225
 
1226
	case ONE:
1227
		a = ABNE;
1228
		if(t->op == OCONST && t->vconst >= (1<<15))
1229
			goto cmpu;
1230
		goto cmp;
1231
 
1232
	case OLT:
1233
		a = ABLT;
1234
		goto cmp;
1235
 
1236
	case OLE:
1237
		a = ABLE;
1238
		goto cmp;
1239
 
1240
	case OGE:
1241
		a = ABGE;
1242
		goto cmp;
1243
 
1244
	case OGT:
1245
		a = ABGT;
1246
		goto cmp;
1247
 
1248
	case OLO:
1249
		a = ABLT;
1250
		goto cmpu;
1251
 
1252
	case OLS:
1253
		a = ABLE;
1254
		goto cmpu;
1255
 
1256
	case OHS:
1257
		a = ABGE;
1258
		goto cmpu;
1259
 
1260
	case OHI:
1261
		a = ABGT;
1262
		goto cmpu;
1263
 
1264
	cmpu:
1265
		uns = 1;
1266
	cmp:
1267
		nextpc();
1268
		p->as = uns? ACMPU: ACMP;
1269
		if(et == TFLOAT)
1270
			p->as = AFCMPU;
1271
		else
1272
		if(et == TDOUBLE)
1273
			p->as = AFCMPU;
1274
		if(f1 != Z)
1275
			naddr(f1, &p->from);
1276
		if(t != Z)
1277
			naddr(t, &p->to);
1278
		if(f1 == Z || t == Z || f2 != Z)
1279
			diag(Z, "bad cmp in gopcode %O", o);
1280
		if(debug['g'])
1281
			print("%P\n", p);
1282
		f1 = Z;
1283
		f2 = Z;
1284
		t = Z;
1285
		break;
1286
	}
1287
	if(a == AGOK)
1288
		diag(Z, "bad in gopcode %O", o);
1289
	gins3(a, f1, f2, t);
1290
}
1291
 
1292
static void
1293
gopcode64(int o, Node *f1, Node *f2, Node *t)
1294
{
1295
	int a1, a2;
1296
	Node nod, nod1, nod2, sh;
1297
	ulong m;
1298
	Prog *p1;
1299
 
1300
	if(t->op != OREGPAIR || f2 != Z && f2->op != OREGPAIR) {
1301
		diag(Z, "bad f2/dest in gopcode64 %O", o);
1302
		return;
1303
	}
1304
	if(f1->op != OCONST &&
1305
	   (typev[f1->type->etype] && f1->op != OREGPAIR || !typev[f1->type->etype] && f1->op != OREGISTER)) {
1306
		diag(Z, "bad f1[%O] in gopcode64 %O", f1->op, o);
1307
		return;
1308
	}
1309
	/* a1 for low-order, a2 for high-order */
1310
	a1 = AGOK;
1311
	a2 = AGOK;
1312
	switch(o) {
1313
	case OASADD:
1314
	case OADD:
1315
		if(f1->op == OCONST && sconst(f1)) {
1316
			if(f2 == Z)
1317
				f2 = t;
1318
			gins3(AADDC, f1, f2->right, t->right);
1319
			if((f1->vconst>>32) == 0)
1320
				gins(AADDZE, f2->left, t->left);
1321
			else if((f1->vconst>>32) == -1)
1322
				gins(AADDME, f2->left, t->left);
1323
			else
1324
				diag(t, "odd vlong ADD: %lld", f1->vconst);
1325
			return;
1326
		}
1327
		a1 = AADDC;
1328
		a2 = AADDE;
1329
		break;
1330
 
1331
	case OASSUB:
1332
	case OSUB:
1333
		a1 = ASUBC;
1334
		a2 = ASUBE;
1335
		break;
1336
 
1337
	case OASOR:
1338
	case OOR:
1339
		if(f1->op == OCONST) {
1340
			gori64(AOR, f1, f2, t);
1341
			return;
1342
		}
1343
		a1 = a2 = AOR;
1344
		break;
1345
 
1346
	case OASAND:
1347
	case OAND:
1348
		if(f1->op == OCONST) {
1349
			gandi64(AANDCC, f1, f2, t);
1350
			return;
1351
		}
1352
		a1 = a2 = AAND;
1353
		break;
1354
 
1355
	case OASXOR:
1356
	case OXOR:
1357
		if(f1->op == OCONST) {
1358
			gori64(AXOR, f1, f2, t);
1359
			return;
1360
		}
1361
		a1 = a2 = AXOR;
1362
		break;
1363
 
1364
	case OASLSHR:
1365
	case OLSHR:
1366
		if(f2 == Z)
1367
			f2 = t;
1368
		if(f1->op == OCONST) {
1369
			if(f1->vconst >= 32) {
1370
				if(f1->vconst == 32)
1371
					gmove(f2->left, t->right);
1372
				else if(f1->vconst < 64)
1373
					gins3(ASRW, nodconst(f1->vconst-32), f2->left, t->right);
1374
				else
1375
					gmove(nodconst(0), t->right);
1376
				gmove(nodconst(0), t->left);
1377
				return;
1378
			}
1379
			if(f1->vconst <= 0) {
1380
				if(f2 != t)
1381
					gmove(f2, t);
1382
				return;
1383
			}
1384
			sh = *nodconst(32 - f1->vconst);
1385
			m = 0xFFFFFFFFUL >> f1->vconst;
1386
			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1387
			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1388
			gins4(ARLWNM, &sh, f2->left, nodconst(m), t->left);
1389
			return;
1390
		}
1391
		regalloc(&nod, &regnode, Z);
1392
		gins3(ASUBC, f1, nodconst(32), &nod);
1393
		gins3(ASRW, f1, f2->right, t->right);
1394
		regalloc(&nod1, &regnode, Z);
1395
		gins3(ASLW, &nod, f2->left, &nod1);
1396
		gins(AOR, &nod1, t->right);
1397
		gins3(AADD, nodconst(-32), f1, &nod);
1398
		gins3(ASRW, &nod, f2->left, &nod1);
1399
		gins(AOR, &nod1, t->right);
1400
		gins3(ASRW, f1, f2->left, t->left);
1401
		regfree(&nod);
1402
		regfree(&nod1);
1403
		return;
1404
 
1405
	case OASASHR:
1406
	case OASHR:
1407
		if(f2 == Z)
1408
			f2 = t;
1409
		if(f1->op == OCONST) {
1410
			if(f1->vconst >= 32) {
1411
				if(f1->vconst == 32)
1412
					gmove(f2->left, t->right);
1413
				else if(f1->vconst < 64)
1414
					gins3(ASRAW, nodconst(f1->vconst-32), f2->left, t->right);
1415
				gins3(ASRAW, nodconst(31), f2->left, t->left);
1416
				if(f1->vconst >= 64) {
1417
					gmove(t->left, t->right);
1418
					return;
1419
				}
1420
				return;
1421
			}
1422
			if(f1->vconst <= 0) {
1423
				if(f2 != t)
1424
					gmove(f2, t);
1425
				return;
1426
			}
1427
			sh = *nodconst(32 - f1->vconst);
1428
			m = 0xFFFFFFFFUL >> f1->vconst;
1429
			gins4(ARLWNM, &sh, f2->right, nodconst(m), t->right);
1430
			gins4(ARLWMI, &sh, f2->left, nodconst(~m), t->right);
1431
			gins3(ASRAW, &sh, f2->left, t->left);
1432
			return;
1433
		}
1434
		regalloc(&nod, &regnode, Z);
1435
		gins3(ASUBC, f1, nodconst(32), &nod);
1436
		gins3(ASRW, f1, f2->right, t->right);
1437
		regalloc(&nod1, &regnode, Z);
1438
		gins3(ASLW, &nod, f2->left, &nod1);
1439
		gins(AOR, &nod1, t->right);
1440
		gins3(AADDCCC, nodconst(-32), f1, &nod);
1441
		gins3(ASRAW, &nod, f2->left, &nod1);
1442
		gins(ABLE, Z, Z);
1443
		p1 = p;
1444
		gins(AMOVW, &nod1, t->right);
1445
		patch(p1, pc);
1446
		gins3(ASRAW, f1, f2->left, t->left);
1447
		regfree(&nod);
1448
		regfree(&nod1);
1449
		return;
1450
 
1451
	case OASASHL:
1452
	case OASHL:
1453
		if(f2 == Z)
1454
			f2 = t;
1455
		if(f1->op == OCONST) {
1456
			if(f1->vconst >= 32) {
1457
				if(f1->vconst == 32)
1458
					gmove(f2->right, t->left);
1459
				else if(f1->vconst >= 64)
1460
					gmove(nodconst(0), t->left);
1461
				else
1462
					gins3(ASLW, nodconst(f1->vconst-32), f2->right, t->left);
1463
				gmove(nodconst(0), t->right);
1464
				return;
1465
			}
1466
			if(f1->vconst <= 0) {
1467
				if(f2 != t)
1468
					gmove(f2, t);
1469
				return;
1470
			}
1471
			m = 0xFFFFFFFFUL << f1->vconst;
1472
			gins4(ARLWNM, f1, f2->left, nodconst(m), t->left);
1473
			gins4(ARLWMI, f1, f2->right, nodconst(~m), t->left);
1474
			gins4(ARLWNM, f1, f2->right, nodconst(m), t->right);
1475
			return;
1476
		}
1477
		regalloc(&nod, &regnode, Z);
1478
		gins3(ASUBC, f1, nodconst(32), &nod);
1479
		gins3(ASLW, f1, f2->left, t->left);
1480
		regalloc(&nod1, &regnode, Z);
1481
		gins3(ASRW, &nod, f2->right, &nod1);
1482
		gins(AOR, &nod1, t->left);
1483
		gins3(AADD, nodconst(-32), f1, &nod);
1484
		gins3(ASLW, &nod, f2->right, &nod1);
1485
		gins(AOR, &nod1, t->left);
1486
		gins3(ASLW, f1, f2->right, t->right);
1487
		regfree(&nod);
1488
		regfree(&nod1);
1489
		return;
1490
 
1491
	case OASLMUL:
1492
	case OLMUL:
1493
	case OASMUL:
1494
	case OMUL:
1495
		if(f2 == Z)
1496
			f2 = t;
1497
		regalloc(&nod, &regnode, Z);
1498
		gins3(AMULLW, f1->right, f2->right, &nod);	/* lo(f2.low*f1.low) */
1499
		regalloc(&nod1, &regnode, Z);
1500
		gins3(AMULHWU, f1->right, f2->right, &nod1);		/* hi(f2.low*f1.low) */
1501
		regalloc(&nod2, &regnode, Z);
1502
		gins3(AMULLW, f2->right, f1->left, &nod2);	/* lo(f2.low*f1.high) */
1503
		gins(AADD, &nod2, &nod1);
1504
		gins3(AMULLW, f1->right, f2->left, &nod2);	/* lo(f2.high*f1.low) */
1505
		gins(AADD, &nod2, &nod1);
1506
		regfree(&nod2);
1507
		gmove(&nod, t->right);
1508
		gmove(&nod1, t->left);
1509
		regfree(&nod);
1510
		regfree(&nod1);
1511
		return;
1512
 
1513
	case OCOM:
1514
		a1 = a2 = ANOR;
1515
		break;
1516
 
1517
	case ONEG:
1518
		gins3(ASUBC, t->right, nodconst(0), t->right);
1519
		gins(ASUBZE, t->left, t->left);
1520
		return;
1521
	}
1522
	if(a1 == AGOK || a2 == AGOK)
1523
		diag(Z, "bad in gopcode64 %O", o);
1524
	if(f1->op == OCONST) {
1525
		if(f2 != Z & f2 != t)
1526
			diag(Z, "bad const in gopcode64 %O", o);
1527
		gins(a1, nod32const(f1->vconst), t->right);
1528
		gins(a2, nod32const(f1->vconst>>32), t->left);
1529
	} else {
1530
		if(f2 != Z && f2 != t) {
1531
			gins3(a1, f1->right, f2->right, t->right);
1532
			gins3(a2, f1->left, f2->left, t->left);
1533
		} else {
1534
			gins(a1, f1->right, t->right);
1535
			gins(a2, f1->left, t->left);
1536
		}
1537
	}
1538
}
1539
 
1540
samaddr(Node *f, Node *t)
1541
{
1542
 
1543
	if(f->op != t->op)
1544
		return 0;
1545
	switch(f->op) {
1546
 
1547
	case OREGISTER:
1548
		if(f->reg != t->reg)
1549
			break;
1550
		return 1;
1551
 
1552
	case OREGPAIR:
1553
		return samaddr(f->left, t->left) && samaddr(f->right, t->right);
1554
	}
1555
	return 0;
1556
}
1557
 
1558
static void
1559
gori64(int a, Node *f1, Node *f2, Node *t)
1560
{
1561
	ulong lo, hi;
1562
 
1563
	if(f2 == Z)
1564
		f2 = t;
1565
	lo = f1->vconst & MASK(32);
1566
	hi = (f1->vconst >> 32) & MASK(32);
1567
	if(lo & 0xFFFF)
1568
		gins3(a, nodconst(lo & 0xFFFF), f2->right, t->right);
1569
	if((lo >> 16) != 0)
1570
		gins3(a, nodconst(lo & 0xFFFF0000UL), f2->right, t->right);
1571
	if(hi & 0xFFFF)
1572
		gins3(a, nodconst(hi & 0xFFFF), f2->left, t->left);
1573
	if((hi >> 16) != 0)
1574
		gins3(a, nodconst(hi & 0xFFFF0000UL), f2->left, t->left);
1575
}
1576
 
1577
static void
1578
gandi64(int a, Node *f1, Node *f2, Node *t)
1579
{
1580
	ulong lo, hi;
1581
 
1582
	if(f2 == Z)
1583
		f2 = t;
1584
	lo = f1->vconst & MASK(32);
1585
	hi = (f1->vconst >> 32) & MASK(32);
1586
	if(lo == 0)
1587
		gins(AMOVW, nodconst(0), t->right);
1588
	else
1589
		gins3(a, nodconst(lo), f2->right, t->right);
1590
	if(hi == 0)
1591
		gins(AMOVW, nodconst(0), t->left);
1592
	else
1593
		gins3(a, nodconst(hi), f2->left, t->left);
1594
}
1595
 
1596
void
1597
gbranch(int o)
1598
{
1599
	int a;
1600
 
1601
	a = AGOK;
1602
	switch(o) {
1603
	case ORETURN:
1604
		a = ARETURN;
1605
		break;
1606
	case OGOTO:
1607
		a = ABR;
1608
		break;
1609
	}
1610
	nextpc();
1611
	if(a == AGOK) {
1612
		diag(Z, "bad in gbranch %O",  o);
1613
		nextpc();
1614
	}
1615
	p->as = a;
1616
}
1617
 
1618
void
1619
patch(Prog *op, long pc)
1620
{
1621
 
1622
	op->to.offset = pc;
1623
	op->to.type = D_BRANCH;
1624
}
1625
 
1626
void
1627
gpseudo(int a, Sym *s, Node *n)
1628
{
1629
 
1630
	nextpc();
1631
	p->as = a;
1632
	p->from.type = D_OREG;
1633
	p->from.sym = s;
1634
	if(a == ATEXT)
1635
		p->reg = (profileflg ? 0 : NOPROF);
1636
	p->from.name = D_EXTERN;
1637
	if(s->class == CSTATIC)
1638
		p->from.name = D_STATIC;
1639
	naddr(n, &p->to);
1640
	if(a == ADATA || a == AGLOBL)
1641
		pc--;
1642
}
1643
 
1644
int
1645
sval(long v)
1646
{
1647
 
1648
	if(v >= -(1<<15) && v < (1<<15))
1649
		return 1;
1650
	return 0;
1651
}
1652
 
1653
int
1654
sconst(Node *n)
1655
{
1656
	vlong vv;
1657
 
1658
	if(n->op == OCONST) {
1659
		if(!typefd[n->type->etype]) {
1660
			vv = n->vconst;
1661
			if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
1662
				return 1;
1663
		}
1664
	}
1665
	return 0;
1666
}
1667
 
1668
int
1669
uconst(Node *n)
1670
{
1671
	vlong vv;
1672
 
1673
	if(n->op == OCONST) {
1674
		if(!typefd[n->type->etype]) {
1675
			vv = n->vconst;
1676
			if(vv >= 0 && vv < (((vlong)1)<<16))
1677
				return 1;
1678
		}
1679
	}
1680
	return 0;
1681
}
1682
 
1683
long
1684
exreg(Type *t)
1685
{
1686
	long o;
1687
 
1688
	if(typechlp[t->etype]) {
1689
		if(exregoffset <= 3)
1690
			return 0;
1691
		o = exregoffset;
1692
		exregoffset--;
1693
		return o;
1694
	}
1695
	if(typefd[t->etype]) {
1696
		if(exfregoffset <= 16)
1697
			return 0;
1698
		o = exfregoffset + NREG;
1699
		exfregoffset--;
1700
		return o;
1701
	}
1702
	return 0;
1703
}
1704
 
1705
schar	ewidth[NTYPE] =
1706
{
1707
	-1,		/* [TXXX] */
1708
	SZ_CHAR,	/* [TCHAR] */
1709
	SZ_CHAR,	/* [TUCHAR] */
1710
	SZ_SHORT,	/* [TSHORT] */
1711
	SZ_SHORT,	/* [TUSHORT] */
1712
	SZ_INT,		/* [TINT] */
1713
	SZ_INT,		/* [TUINT] */
1714
	SZ_LONG,	/* [TLONG] */
1715
	SZ_LONG,	/* [TULONG] */
1716
	SZ_VLONG,	/* [TVLONG] */
1717
	SZ_VLONG,	/* [TUVLONG] */
1718
	SZ_FLOAT,	/* [TFLOAT] */
1719
	SZ_DOUBLE,	/* [TDOUBLE] */
1720
	SZ_IND,		/* [TIND] */
1721
	0,		/* [TFUNC] */
1722
	-1,		/* [TARRAY] */
1723
	0,		/* [TVOID] */
1724
	-1,		/* [TSTRUCT] */
1725
	-1,		/* [TUNION] */
1726
	SZ_INT,		/* [TENUM] */
1727
};
1728
long	ncast[NTYPE] =
1729
{
1730
	0,				/* [TXXX] */
1731
	BCHAR|BUCHAR,			/* [TCHAR] */
1732
	BCHAR|BUCHAR,			/* [TUCHAR] */
1733
	BSHORT|BUSHORT,			/* [TSHORT] */
1734
	BSHORT|BUSHORT,			/* [TUSHORT] */
1735
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
1736
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
1737
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
1738
	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
1739
	BVLONG|BUVLONG,			/* [TVLONG] */
1740
	BVLONG|BUVLONG,			/* [TUVLONG] */
1741
	BFLOAT,				/* [TFLOAT] */
1742
	BDOUBLE,			/* [TDOUBLE] */
1743
	BLONG|BULONG|BIND,		/* [TIND] */
1744
	0,				/* [TFUNC] */
1745
	0,				/* [TARRAY] */
1746
	0,				/* [TVOID] */
1747
	BSTRUCT,			/* [TSTRUCT] */
1748
	BUNION,				/* [TUNION] */
1749
	0,				/* [TENUM] */
1750
};