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/5l/asm.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	"l.h"
2
 
3
long	OFFSET;
4
 
5
static Prog *PP;
6
 
7
long
8
entryvalue(void)
9
{
10
	char *a;
11
	Sym *s;
12
 
13
	a = INITENTRY;
14
	if(*a >= '0' && *a <= '9')
15
		return atolwhex(a);
16
	s = lookup(a, 0);
17
	if(s->type == 0)
18
		return INITTEXT;
19
	switch(s->type) {
20
	case STEXT:
21
	case SLEAF:
22
		break;
23
	case SDATA:
24
		if(dlm)
25
			return s->value+INITDAT;
26
	default:
27
		diag("entry not text: %s", s->name);
28
	}
29
	return s->value;
30
}
31
 
32
void
33
asmb(void)
34
{
35
	Prog *p;
36
	long t, etext;
37
	Optab *o;
38
 
39
	if(debug['v'])
40
		Bprint(&bso, "%5.2f asm\n", cputime());
41
	Bflush(&bso);
42
	OFFSET = HEADR;
43
	seek(cout, OFFSET, 0);
44
	pc = INITTEXT;
45
	for(p = firstp; p != P; p = p->link) {
46
		if(p->as == ATEXT) {
47
			curtext = p;
48
			autosize = p->to.offset + 4;
49
		}
50
		if(p->pc != pc) {
51
			diag("phase error %lux sb %lux",
52
				p->pc, pc);
53
			if(!debug['a'])
54
				prasm(curp);
55
			pc = p->pc;
56
		}
57
		curp = p;
58
		o = oplook(p);	/* could probably avoid this call */
59
		asmout(p, o);
60
		pc += o->size;
61
	}
62
 
63
	if(debug['a'])
64
		Bprint(&bso, "\n");
65
	Bflush(&bso);
66
	cflush();
67
 
68
	/* output strings in text segment */
69
	etext = INITTEXT + textsize;
70
	for(t = pc; t < etext; t += sizeof(buf)-100) {
71
		if(etext-t > sizeof(buf)-100)
72
			datblk(t, sizeof(buf)-100, 1);
73
		else
74
			datblk(t, etext-t, 1);
75
	}
76
 
77
	curtext = P;
78
	switch(HEADTYPE) {
79
	case 0:
80
	case 1:
81
	case 2:
82
	case 5:
83
	case 7:
84
		OFFSET = HEADR+textsize;
85
		seek(cout, OFFSET, 0);
86
		break;
87
	case 3:
88
	case 6:	/* no header, padded segments */
89
		OFFSET = rnd(HEADR+textsize, 4096);
90
		seek(cout, OFFSET, 0);
91
		break;
92
	}
93
	if(dlm){
94
		char buf[8];
95
 
96
		write(cout, buf, INITDAT-textsize);
97
		textsize = INITDAT;
98
	}
99
	for(t = 0; t < datsize; t += sizeof(buf)-100) {
100
		if(datsize-t > sizeof(buf)-100)
101
			datblk(t, sizeof(buf)-100, 0);
102
		else
103
			datblk(t, datsize-t, 0);
104
	}
105
 
106
	symsize = 0;
107
	lcsize = 0;
108
	if(!debug['s']) {
109
		if(debug['v'])
110
			Bprint(&bso, "%5.2f sym\n", cputime());
111
		Bflush(&bso);
112
		switch(HEADTYPE) {
113
		case 0:
114
		case 1:
115
		case 4:
116
		case 5:
117
			debug['s'] = 1;
118
			break;
119
		case 2:
120
			OFFSET = HEADR+textsize+datsize;
121
			seek(cout, OFFSET, 0);
122
			break;
123
		case 3:
124
		case 6:	/* no header, padded segments */
125
			OFFSET += rnd(datsize, 4096);
126
			seek(cout, OFFSET, 0);
127
			break;
128
		case 7:
129
			break;
130
		}
131
		if(!debug['s'])
132
			asmsym();
133
		if(debug['v'])
134
			Bprint(&bso, "%5.2f pc\n", cputime());
135
		Bflush(&bso);
136
		if(!debug['s'])
137
			asmlc();
138
		if(dlm)
139
			asmdyn();
140
		cflush();
141
	}
142
	else if(dlm){
143
		seek(cout, HEADR+textsize+datsize, 0);
144
		asmdyn();
145
		cflush();
146
	}
147
 
148
	if(debug['v'])
149
		Bprint(&bso, "%5.2f header\n", cputime());
150
	Bflush(&bso);
151
	OFFSET = 0;
152
	seek(cout, OFFSET, 0);
153
	switch(HEADTYPE) {
154
	case 0:	/* no header */
155
	case 6:	/* no header, padded segments */
156
		break;
157
	case 1:	/* aif for risc os */
158
		lputl(0xe1a00000);		/* NOP - decompress code */
159
		lputl(0xe1a00000);		/* NOP - relocation code */
160
		lputl(0xeb000000 + 12);		/* BL - zero init code */
161
		lputl(0xeb000000 +
162
			(entryvalue()
163
			 - INITTEXT
164
			 + HEADR
165
			 - 12
166
			 - 8) / 4);		/* BL - entry code */
167
 
168
		lputl(0xef000011);		/* SWI - exit code */
169
		lputl(textsize+HEADR);		/* text size */
170
		lputl(datsize);			/* data size */
171
		lputl(0);			/* sym size */
172
 
173
		lputl(bsssize);			/* bss size */
174
		lputl(0);			/* sym type */
175
		lputl(INITTEXT-HEADR);		/* text addr */
176
		lputl(0);			/* workspace - ignored */
177
 
178
		lputl(32);			/* addr mode / data addr flag */
179
		lputl(0);			/* data addr */
180
		for(t=0; t<2; t++)
181
			lputl(0);		/* reserved */
182
 
183
		for(t=0; t<15; t++)
184
			lputl(0xe1a00000);	/* NOP - zero init code */
185
		lputl(0xe1a0f00e);		/* B (R14) - zero init return */
186
		break;
187
	case 2:	/* plan 9 */
188
		if(dlm)
189
			lput(0x80000000|0x647);	/* magic */
190
		else
191
			lput(0x647);			/* magic */
192
		lput(textsize);			/* sizes */
193
		lput(datsize);
194
		lput(bsssize);
195
		lput(symsize);			/* nsyms */
196
		lput(entryvalue());		/* va of entry */
197
		lput(0L);
198
		lput(lcsize);
199
		break;
200
	case 3:	/* boot for NetBSD */
201
		lput((143<<16)|0413);		/* magic */
202
		lputl(rnd(HEADR+textsize, 4096));
203
		lputl(rnd(datsize, 4096));
204
		lputl(bsssize);
205
		lputl(symsize);			/* nsyms */
206
		lputl(entryvalue());		/* va of entry */
207
		lputl(0L);
208
		lputl(0L);
209
		break;
210
	case 4: /* boot for IXP1200 */
211
		break;
212
	case 5: /* boot for ipaq */
213
		lputl(0xe3300000);		/* nop */
214
		lputl(0xe3300000);		/* nop */
215
		lputl(0xe3300000);		/* nop */
216
		lputl(0xe3300000);		/* nop */
217
		break;
218
	case 7:	/* elf */
219
		debug['S'] = 1;			/* symbol table */
220
		elf32(ARM, ELFDATA2LSB, 0, nil);
221
		break;
222
	}
223
	cflush();
224
}
225
 
226
void
227
strnput(char *s, int n)
228
{
229
	for(; *s; s++){
230
		cput(*s);
231
		n--;
232
	}
233
	for(; n > 0; n--)
234
		cput(0);
235
}
236
 
237
void
238
cput(int c)
239
{
240
	cbp[0] = c;
241
	cbp++;
242
	cbc--;
243
	if(cbc <= 0)
244
		cflush();
245
}
246
 
247
void
248
wput(long l)
249
{
250
 
251
	cbp[0] = l>>8;
252
	cbp[1] = l;
253
	cbp += 2;
254
	cbc -= 2;
255
	if(cbc <= 0)
256
		cflush();
257
}
258
 
259
void
260
wputl(long l)
261
{
262
 
263
	cbp[0] = l;
264
	cbp[1] = l>>8;
265
	cbp += 2;
266
	cbc -= 2;
267
	if(cbc <= 0)
268
		cflush();
269
}
270
 
271
void
272
lput(long l)
273
{
274
 
275
	cbp[0] = l>>24;
276
	cbp[1] = l>>16;
277
	cbp[2] = l>>8;
278
	cbp[3] = l;
279
	cbp += 4;
280
	cbc -= 4;
281
	if(cbc <= 0)
282
		cflush();
283
}
284
 
285
void
286
lputl(long l)
287
{
288
 
289
	cbp[3] = l>>24;
290
	cbp[2] = l>>16;
291
	cbp[1] = l>>8;
292
	cbp[0] = l;
293
	cbp += 4;
294
	cbc -= 4;
295
	if(cbc <= 0)
296
		cflush();
297
}
298
 
299
void
300
llput(vlong v)
301
{
302
	lput(v>>32);
303
	lput(v);
304
}
305
 
306
void
307
llputl(vlong v)
308
{
309
	lputl(v);
310
	lputl(v>>32);
311
}
312
 
313
void
314
cflush(void)
315
{
316
	int n;
317
 
318
	n = sizeof(buf.cbuf) - cbc;
319
	if(n)
320
		write(cout, buf.cbuf, n);
321
	cbp = buf.cbuf;
322
	cbc = sizeof(buf.cbuf);
323
}
324
 
325
void
326
nopstat(char *f, Count *c)
327
{
328
	if(c->outof)
329
	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
330
		c->outof - c->count, c->outof,
331
		(double)(c->outof - c->count)/c->outof);
332
}
333
 
334
void
335
asmsym(void)
336
{
337
	Prog *p;
338
	Auto *a;
339
	Sym *s;
340
	int h;
341
 
342
	s = lookup("etext", 0);
343
	if(s->type == STEXT)
344
		putsymb(s->name, 'T', s->value, s->version);
345
 
346
	for(h=0; h<NHASH; h++)
347
		for(s=hash[h]; s!=S; s=s->link)
348
			switch(s->type) {
349
			case SCONST:
350
				putsymb(s->name, 'D', s->value, s->version);
351
				continue;
352
 
353
			case SDATA:
354
				putsymb(s->name, 'D', s->value+INITDAT, s->version);
355
				continue;
356
 
357
			case SBSS:
358
				putsymb(s->name, 'B', s->value+INITDAT, s->version);
359
				continue;
360
 
361
			case SSTRING:
362
				putsymb(s->name, 'T', s->value, s->version);
363
				continue;
364
 
365
			case SFILE:
366
				putsymb(s->name, 'f', s->value, s->version);
367
				continue;
368
			}
369
 
370
	for(p=textp; p!=P; p=p->cond) {
371
		s = p->from.sym;
372
		if(s->type != STEXT && s->type != SLEAF)
373
			continue;
374
 
375
		/* filenames first */
376
		for(a=p->to.autom; a; a=a->link)
377
			if(a->type == D_FILE)
378
				putsymb(a->asym->name, 'z', a->aoffset, 0);
379
			else
380
			if(a->type == D_FILE1)
381
				putsymb(a->asym->name, 'Z', a->aoffset, 0);
382
 
383
		if(s->type == STEXT)
384
			putsymb(s->name, 'T', s->value, s->version);
385
		else
386
			putsymb(s->name, 'L', s->value, s->version);
387
 
388
		/* frame, auto and param after */
389
		putsymb(".frame", 'm', p->to.offset+4, 0);
390
		for(a=p->to.autom; a; a=a->link)
391
			if(a->type == D_AUTO)
392
				putsymb(a->asym->name, 'a', -a->aoffset, 0);
393
			else
394
			if(a->type == D_PARAM)
395
				putsymb(a->asym->name, 'p', a->aoffset, 0);
396
	}
397
	if(debug['v'] || debug['n'])
398
		Bprint(&bso, "symsize = %lud\n", symsize);
399
	Bflush(&bso);
400
}
401
 
402
void
403
putsymb(char *s, int t, long v, int ver)
404
{
405
	int i, f;
406
 
407
	if(t == 'f')
408
		s++;
409
	lput(v);
410
	if(ver)
411
		t += 'a' - 'A';
412
	cput(t+0x80);			/* 0x80 is variable length */
413
 
414
	if(t == 'Z' || t == 'z') {
415
		cput(s[0]);
416
		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
417
			cput(s[i]);
418
			cput(s[i+1]);
419
		}
420
		cput(0);
421
		cput(0);
422
		i++;
423
	}
424
	else {
425
		for(i=0; s[i]; i++)
426
			cput(s[i]);
427
		cput(0);
428
	}
429
	symsize += 4 + 1 + i + 1;
430
 
431
	if(debug['n']) {
432
		if(t == 'z' || t == 'Z') {
433
			Bprint(&bso, "%c %.8lux ", t, v);
434
			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
435
				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
436
				Bprint(&bso, "/%x", f);
437
			}
438
			Bprint(&bso, "\n");
439
			return;
440
		}
441
		if(ver)
442
			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
443
		else
444
			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
445
	}
446
}
447
 
448
#define	MINLC	4
449
void
450
asmlc(void)
451
{
452
	long oldpc, oldlc;
453
	Prog *p;
454
	long v, s;
455
 
456
	oldpc = INITTEXT;
457
	oldlc = 0;
458
	for(p = firstp; p != P; p = p->link) {
459
		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
460
			if(p->as == ATEXT)
461
				curtext = p;
462
			if(debug['V'])
463
				Bprint(&bso, "%6lux %P\n",
464
					p->pc, p);
465
			continue;
466
		}
467
		if(debug['V'])
468
			Bprint(&bso, "\t\t%6ld", lcsize);
469
		v = (p->pc - oldpc) / MINLC;
470
		while(v) {
471
			s = 127;
472
			if(v < 127)
473
				s = v;
474
			cput(s+128);	/* 129-255 +pc */
475
			if(debug['V'])
476
				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
477
			v -= s;
478
			lcsize++;
479
		}
480
		s = p->line - oldlc;
481
		oldlc = p->line;
482
		oldpc = p->pc + MINLC;
483
		if(s > 64 || s < -64) {
484
			cput(0);	/* 0 vv +lc */
485
			cput(s>>24);
486
			cput(s>>16);
487
			cput(s>>8);
488
			cput(s);
489
			if(debug['V']) {
490
				if(s > 0)
491
					Bprint(&bso, " lc+%ld(%d,%ld)\n",
492
						s, 0, s);
493
				else
494
					Bprint(&bso, " lc%ld(%d,%ld)\n",
495
						s, 0, s);
496
				Bprint(&bso, "%6lux %P\n",
497
					p->pc, p);
498
			}
499
			lcsize += 5;
500
			continue;
501
		}
502
		if(s > 0) {
503
			cput(0+s);	/* 1-64 +lc */
504
			if(debug['V']) {
505
				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
506
				Bprint(&bso, "%6lux %P\n",
507
					p->pc, p);
508
			}
509
		} else {
510
			cput(64-s);	/* 65-128 -lc */
511
			if(debug['V']) {
512
				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
513
				Bprint(&bso, "%6lux %P\n",
514
					p->pc, p);
515
			}
516
		}
517
		lcsize++;
518
	}
519
	while(lcsize & 1) {
520
		s = 129;
521
		cput(s);
522
		lcsize++;
523
	}
524
	if(debug['v'] || debug['V'])
525
		Bprint(&bso, "lcsize = %ld\n", lcsize);
526
	Bflush(&bso);
527
}
528
 
529
void
530
datblk(long s, long n, int str)
531
{
532
	Sym *v;
533
	Prog *p;
534
	char *cast;
535
	long a, l, fl, j, d;
536
	int i, c;
537
 
538
	memset(buf.dbuf, 0, n+100);
539
	for(p = datap; p != P; p = p->link) {
540
		if(str != (p->from.sym->type == SSTRING))
541
			continue;
542
		curp = p;
543
		a = p->from.sym->value + p->from.offset;
544
		l = a - s;
545
		c = p->reg;
546
		i = 0;
547
		if(l < 0) {
548
			if(l+c <= 0)
549
				continue;
550
			while(l < 0) {
551
				l++;
552
				i++;
553
			}
554
		}
555
		if(l >= n)
556
			continue;
557
		if(p->as != AINIT && p->as != ADYNT) {
558
			for(j=l+(c-i)-1; j>=l; j--)
559
				if(buf.dbuf[j]) {
560
					print("%P\n", p);
561
					diag("multiple initialization");
562
					break;
563
				}
564
		}
565
		switch(p->to.type) {
566
		default:
567
			diag("unknown mode in initialization%P", p);
568
			break;
569
 
570
		case D_FCONST:
571
			switch(c) {
572
			default:
573
			case 4:
574
				fl = ieeedtof(p->to.ieee);
575
				cast = (char*)&fl;
576
				for(; i<c; i++) {
577
					buf.dbuf[l] = cast[fnuxi4[i]];
578
					l++;
579
				}
580
				break;
581
			case 8:
582
				cast = (char*)p->to.ieee;
583
				for(; i<c; i++) {
584
					buf.dbuf[l] = cast[fnuxi8[i]];
585
					l++;
586
				}
587
				break;
588
			}
589
			break;
590
 
591
		case D_SCONST:
592
			for(; i<c; i++) {
593
				buf.dbuf[l] = p->to.sval[i];
594
				l++;
595
			}
596
			break;
597
 
598
		case D_CONST:
599
			d = p->to.offset;
600
			v = p->to.sym;
601
			if(v) {
602
				switch(v->type) {
603
				case SUNDEF:
604
					ckoff(v, d);
605
				case STEXT:
606
				case SLEAF:
607
				case SSTRING:
608
					d += p->to.sym->value;
609
					break;
610
				case SDATA:
611
				case SBSS:
612
					d += p->to.sym->value + INITDAT;
613
				}
614
				if(dlm)
615
					dynreloc(v, a+INITDAT, 1);
616
			}
617
			cast = (char*)&d;
618
			switch(c) {
619
			default:
620
				diag("bad nuxi %d %d%P", c, i, curp);
621
				break;
622
			case 1:
623
				for(; i<c; i++) {
624
					buf.dbuf[l] = cast[inuxi1[i]];
625
					l++;
626
				}
627
				break;
628
			case 2:
629
				for(; i<c; i++) {
630
					buf.dbuf[l] = cast[inuxi2[i]];
631
					l++;
632
				}
633
				break;
634
			case 4:
635
				for(; i<c; i++) {
636
					buf.dbuf[l] = cast[inuxi4[i]];
637
					l++;
638
				}
639
				break;
640
			}
641
			break;
642
		}
643
	}
644
	write(cout, buf.dbuf, n);
645
}
646
 
647
void
648
asmout(Prog *p, Optab *o)
649
{
650
	long o1, o2, o3, o4, o5, o6, v;
651
	int r, rf, rt, rt2;
652
	Sym *s;
653
 
654
PP = p;
655
	o1 = 0;
656
	o2 = 0;
657
	o3 = 0;
658
	o4 = 0;
659
	o5 = 0;
660
	o6 = 0;
661
	switch(o->type) {
662
	default:
663
		diag("unknown asm %d", o->type);
664
		prasm(p);
665
		break;
666
 
667
	case 0:		/* pseudo ops */
668
		break;
669
 
670
	case 1:		/* op R,[R],R */
671
		o1 = oprrr(p->as, p->scond);
672
		rf = p->from.reg;
673
		rt = p->to.reg;
674
		r = p->reg;
675
		if(p->to.type == D_NONE)
676
			rt = 0;
677
		if(p->as == AMOVW || p->as == AMVN)
678
			r = 0;
679
		else if(r == NREG)
680
			r = rt;
681
		o1 |= rf | (r<<16) | (rt<<12);
682
		break;
683
 
684
	case 2:		/* movbu $I,[R],R */
685
		aclass(&p->from);
686
		o1 = oprrr(p->as, p->scond);
687
		o1 |= immrot(instoffset);
688
		rt = p->to.reg;
689
		r = p->reg;
690
		if(p->to.type == D_NONE)
691
			rt = 0;
692
		if(p->as == AMOVW || p->as == AMVN)
693
			r = 0;
694
		else if(r == NREG)
695
			r = rt;
696
		o1 |= (r<<16) | (rt<<12);
697
		break;
698
 
699
	case 3:		/* add R<<[IR],[R],R */
700
	mov:
701
		aclass(&p->from);
702
		o1 = oprrr(p->as, p->scond);
703
		o1 |= p->from.offset;
704
		rt = p->to.reg;
705
		r = p->reg;
706
		if(p->to.type == D_NONE)
707
			rt = 0;
708
		if(p->as == AMOVW || p->as == AMVN)
709
			r = 0;
710
		else if(r == NREG)
711
			r = rt;
712
		o1 |= (r<<16) | (rt<<12);
713
		break;
714
 
715
	case 4:		/* add $I,[R],R */
716
		aclass(&p->from);
717
		o1 = oprrr(AADD, p->scond);
718
		o1 |= immrot(instoffset);
719
		r = p->from.reg;
720
		if(r == NREG)
721
			r = o->param;
722
		o1 |= r << 16;
723
		o1 |= p->to.reg << 12;
724
		break;
725
 
726
	case 5:		/* bra s */
727
		v = -8;
728
		if(p->cond == UP) {
729
			s = p->to.sym;
730
			if(s->type != SUNDEF)
731
				diag("bad branch sym type");
732
			v = (ulong)s->value >> (Roffset-2);
733
			dynreloc(s, p->pc, 0);
734
		}
735
		else if(p->cond != P)
736
			v = (p->cond->pc - pc) - 8;
737
		o1 = opbra(p->as, p->scond);
738
		o1 |= (v >> 2) & 0xffffff;
739
		break;
740
 
741
	case 6:		/* b ,O(R) -> add $O,R,PC */
742
		aclass(&p->to);
743
		o1 = oprrr(AADD, p->scond);
744
		o1 |= immrot(instoffset);
745
		o1 |= p->to.reg << 16;
746
		o1 |= REGPC << 12;
747
		break;
748
 
749
	case 7:		/* bl ,O(R) -> mov PC,link; add $O,R,PC */
750
		aclass(&p->to);
751
		o1 = oprrr(AADD, p->scond);
752
		o1 |= immrot(0);
753
		o1 |= REGPC << 16;
754
		o1 |= REGLINK << 12;
755
 
756
		o2 = oprrr(AADD, p->scond);
757
		o2 |= immrot(instoffset);
758
		o2 |= p->to.reg << 16;
759
		o2 |= REGPC << 12;
760
		break;
761
 
762
	case 8:		/* sll $c,[R],R -> mov (R<<$c),R */
763
		aclass(&p->from);
764
		o1 = oprrr(p->as, p->scond);
765
		r = p->reg;
766
		if(r == NREG)
767
			r = p->to.reg;
768
		o1 |= r;
769
		o1 |= (instoffset&31) << 7;
770
		o1 |= p->to.reg << 12;
771
		break;
772
 
773
	case 9:		/* sll R,[R],R -> mov (R<<R),R */
774
		o1 = oprrr(p->as, p->scond);
775
		r = p->reg;
776
		if(r == NREG)
777
			r = p->to.reg;
778
		o1 |= r;
779
		o1 |= (p->from.reg << 8) | (1<<4);
780
		o1 |= p->to.reg << 12;
781
		break;
782
 
783
	case 10:	/* swi [$con] */
784
		o1 = oprrr(p->as, p->scond);
785
		if(p->to.type != D_NONE) {
786
			aclass(&p->to);
787
			o1 |= instoffset & 0xffffff;
788
		}
789
		break;
790
 
791
	case 11:	/* word */
792
		switch(aclass(&p->to)) {
793
		case C_LCON:
794
			if(!dlm)
795
				break;
796
			if(p->to.name != D_EXTERN && p->to.name != D_STATIC)
797
				break;
798
		case C_ADDR:
799
			if(p->to.sym->type == SUNDEF)
800
				ckoff(p->to.sym, p->to.offset);
801
			dynreloc(p->to.sym, p->pc, 1);
802
		}
803
		o1 = instoffset;
804
		break;
805
 
806
	case 12:	/* movw $lcon, reg */
807
		o1 = omvl(p, &p->from, p->to.reg);
808
		break;
809
 
810
	case 13:	/* op $lcon, [R], R */
811
		o1 = omvl(p, &p->from, REGTMP);
812
		if(!o1)
813
			break;
814
		o2 = oprrr(p->as, p->scond);
815
		o2 |= REGTMP;
816
		r = p->reg;
817
		if(p->as == AMOVW || p->as == AMVN)
818
			r = 0;
819
		else if(r == NREG)
820
			r = p->to.reg;
821
		o2 |= r << 16;
822
		if(p->to.type != D_NONE)
823
			o2 |= p->to.reg << 12;
824
		break;
825
 
826
	case 14:	/* movb/movbu/movh/movhu R,R */
827
		o1 = oprrr(ASLL, p->scond);
828
 
829
		if(p->as == AMOVBU || p->as == AMOVHU)
830
			o2 = oprrr(ASRL, p->scond);
831
		else
832
			o2 = oprrr(ASRA, p->scond);
833
 
834
		r = p->to.reg;
835
		o1 |= (p->from.reg)|(r<<12);
836
		o2 |= (r)|(r<<12);
837
		if(p->as == AMOVB || p->as == AMOVBU) {
838
			o1 |= (24<<7);
839
			o2 |= (24<<7);
840
		} else {
841
			o1 |= (16<<7);
842
			o2 |= (16<<7);
843
		}
844
		break;
845
 
846
	case 15:	/* mul r,[r,]r */
847
		o1 = oprrr(p->as, p->scond);
848
		rf = p->from.reg;
849
		rt = p->to.reg;
850
		r = p->reg;
851
		if(r == NREG)
852
			r = rt;
853
		if(rt == r) {
854
			r = rf;
855
			rf = rt;
856
		}
857
		if(0)
858
		if(rt == r || rf == REGPC || r == REGPC || rt == REGPC) {
859
			diag("bad registers in MUL");
860
			prasm(p);
861
		}
862
		o1 |= (rf<<8) | r | (rt<<16);
863
		break;
864
 
865
 
866
	case 16:	/* div r,[r,]r */
867
		o1 = 0xf << 28;
868
		o2 = 0;
869
		break;
870
 
871
	case 17:
872
		o1 = oprrr(p->as, p->scond);
873
		rf = p->from.reg;
874
		rt = p->to.reg;
875
		rt2 = p->to.offset;
876
		r = p->reg;
877
		o1 |= (rf<<8) | r | (rt<<16) | (rt2<<12);
878
		break;
879
 
880
	case 20:	/* mov/movb/movbu R,O(R) */
881
		aclass(&p->to);
882
		r = p->to.reg;
883
		if(r == NREG)
884
			r = o->param;
885
		o1 = osr(p->as, p->from.reg, instoffset, r, p->scond);
886
		break;
887
 
888
	case 21:	/* mov/movbu O(R),R -> lr */
889
		aclass(&p->from);
890
		r = p->from.reg;
891
		if(r == NREG)
892
			r = o->param;
893
		o1 = olr(instoffset, r, p->to.reg, p->scond);
894
		if(p->as != AMOVW)
895
			o1 |= 1<<22;
896
		break;
897
 
898
	case 22:	/* movb/movh/movhu O(R),R -> lr,shl,shr */
899
		aclass(&p->from);
900
		r = p->from.reg;
901
		if(r == NREG)
902
			r = o->param;
903
		o1 = olr(instoffset, r, p->to.reg, p->scond);
904
 
905
		o2 = oprrr(ASLL, p->scond);
906
		o3 = oprrr(ASRA, p->scond);
907
		r = p->to.reg;
908
		if(p->as == AMOVB) {
909
			o2 |= (24<<7)|(r)|(r<<12);
910
			o3 |= (24<<7)|(r)|(r<<12);
911
		} else {
912
			o2 |= (16<<7)|(r)|(r<<12);
913
			if(p->as == AMOVHU)
914
				o3 = oprrr(ASRL, p->scond);
915
			o3 |= (16<<7)|(r)|(r<<12);
916
		}
917
		break;
918
 
919
	case 23:	/* movh/movhu R,O(R) -> sb,sb */
920
		aclass(&p->to);
921
		r = p->to.reg;
922
		if(r == NREG)
923
			r = o->param;
924
		o1 = osr(AMOVH, p->from.reg, instoffset, r, p->scond);
925
 
926
		o2 = oprrr(ASRL, p->scond);
927
		o2 |= (8<<7)|(p->from.reg)|(REGTMP<<12);
928
 
929
		o3 = osr(AMOVH, REGTMP, instoffset+1, r, p->scond);
930
		break;
931
 
932
	case 30:	/* mov/movb/movbu R,L(R) */
933
		o1 = omvl(p, &p->to, REGTMP);
934
		if(!o1)
935
			break;
936
		r = p->to.reg;
937
		if(r == NREG)
938
			r = o->param;
939
		o2 = osrr(p->from.reg, REGTMP,r, p->scond);
940
		if(p->as != AMOVW)
941
			o2 |= 1<<22;
942
		break;
943
 
944
	case 31:	/* mov/movbu L(R),R -> lr[b] */
945
	case 32:	/* movh/movb L(R),R -> lr[b] */
946
		o1 = omvl(p, &p->from, REGTMP);
947
		if(!o1)
948
			break;
949
		r = p->from.reg;
950
		if(r == NREG)
951
			r = o->param;
952
		o2 = olrr(REGTMP,r, p->to.reg, p->scond);
953
		if(p->as == AMOVBU || p->as == AMOVB)
954
			o2 |= 1<<22;
955
		if(o->type == 31)
956
			break;
957
 
958
		o3 = oprrr(ASLL, p->scond);
959
 
960
		if(p->as == AMOVBU || p->as == AMOVHU)
961
			o4 = oprrr(ASRL, p->scond);
962
		else
963
			o4 = oprrr(ASRA, p->scond);
964
 
965
		r = p->to.reg;
966
		o3 |= (r)|(r<<12);
967
		o4 |= (r)|(r<<12);
968
		if(p->as == AMOVB || p->as == AMOVBU) {
969
			o3 |= (24<<7);
970
			o4 |= (24<<7);
971
		} else {
972
			o3 |= (16<<7);
973
			o4 |= (16<<7);
974
		}
975
		break;
976
 
977
	case 33:	/* movh/movhu R,L(R) -> sb, sb */
978
		o1 = omvl(p, &p->to, REGTMP);
979
		if(!o1)
980
			break;
981
		r = p->to.reg;
982
		if(r == NREG)
983
			r = o->param;
984
		o2 = osrr(p->from.reg, REGTMP, r, p->scond);
985
		o2 |= (1<<22) ;
986
 
987
		o3 = oprrr(ASRL, p->scond);
988
		o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12);
989
		o3 |= (1<<6);	/* ROR 8 */
990
 
991
		o4 = oprrr(AADD, p->scond);
992
		o4 |= (REGTMP << 12) | (REGTMP << 16);
993
		o4 |= immrot(1);
994
 
995
		o5 = osrr(p->from.reg, REGTMP,r,p->scond);
996
		o5 |= (1<<22);
997
 
998
		o6 = oprrr(ASRL, p->scond);
999
		o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12);
1000
		o6 |= (1<<6);	/* ROL 8 */
1001
 
1002
		break;
1003
 
1004
	case 34:	/* mov $lacon,R */
1005
		o1 = omvl(p, &p->from, REGTMP);
1006
		if(!o1)
1007
			break;
1008
 
1009
		o2 = oprrr(AADD, p->scond);
1010
		o2 |= REGTMP;
1011
		r = p->from.reg;
1012
		if(r == NREG)
1013
			r = o->param;
1014
		o2 |= r << 16;
1015
		if(p->to.type != D_NONE)
1016
			o2 |= p->to.reg << 12;
1017
		break;
1018
 
1019
	case 35:	/* mov PSR,R */
1020
		o1 = (2<<23) | (0xf<<16) | (0<<0);
1021
		o1 |= (p->scond & C_SCOND) << 28;
1022
		o1 |= (p->from.reg & 1) << 22;
1023
		o1 |= p->to.reg << 12;
1024
		break;
1025
 
1026
	case 36:	/* mov R,PSR */
1027
		o1 = (2<<23) | (0x29f<<12) | (0<<4);
1028
		if(p->scond & C_FBIT)
1029
			o1 ^= 0x010 << 12;
1030
		o1 |= (p->scond & C_SCOND) << 28;
1031
		o1 |= (p->to.reg & 1) << 22;
1032
		o1 |= p->from.reg << 0;
1033
		break;
1034
 
1035
	case 37:	/* mov $con,PSR */
1036
		aclass(&p->from);
1037
		o1 = (2<<23) | (0x29f<<12) | (0<<4);
1038
		if(p->scond & C_FBIT)
1039
			o1 ^= 0x010 << 12;
1040
		o1 |= (p->scond & C_SCOND) << 28;
1041
		o1 |= immrot(instoffset);
1042
		o1 |= (p->to.reg & 1) << 22;
1043
		o1 |= p->from.reg << 0;
1044
		break;
1045
 
1046
	case 38:	/* movm $con,oreg -> stm */
1047
		o1 = (0x4 << 25);
1048
		o1 |= p->from.offset & 0xffff;
1049
		o1 |= p->to.reg << 16;
1050
		aclass(&p->to);
1051
		goto movm;
1052
 
1053
	case 39:	/* movm oreg,$con -> ldm */
1054
		o1 = (0x4 << 25) | (1 << 20);
1055
		o1 |= p->to.offset & 0xffff;
1056
		o1 |= p->from.reg << 16;
1057
		aclass(&p->from);
1058
	movm:
1059
		if(instoffset != 0)
1060
			diag("offset must be zero in MOVM");
1061
		o1 |= (p->scond & C_SCOND) << 28;
1062
		if(p->scond & C_PBIT)
1063
			o1 |= 1 << 24;
1064
		if(p->scond & C_UBIT)
1065
			o1 |= 1 << 23;
1066
		if(p->scond & C_SBIT)
1067
			o1 |= 1 << 22;
1068
		if(p->scond & C_WBIT)
1069
			o1 |= 1 << 21;
1070
		break;
1071
 
1072
	case 40:	/* swp oreg,reg,reg */
1073
		aclass(&p->from);
1074
		if(instoffset != 0)
1075
			diag("offset must be zero in SWP");
1076
		o1 = (0x2<<23) | (0x9<<4);
1077
		if(p->as != ASWPW)
1078
			o1 |= 1 << 22;
1079
		o1 |= p->from.reg << 16;
1080
		o1 |= p->reg << 0;
1081
		o1 |= p->to.reg << 12;
1082
		o1 |= (p->scond & C_SCOND) << 28;
1083
		break;
1084
 
1085
	case 41:	/* rfe -> movm.s.w.u 0(r13),[r15] */
1086
		o1 = 0xe8fd8000;
1087
		break;
1088
 
1089
	case 50:	/* floating point store */
1090
		v = regoff(&p->to);
1091
		r = p->to.reg;
1092
		if(r == NREG)
1093
			r = o->param;
1094
		o1 = ofsr(p->as, p->from.reg, v, r, p->scond, p);
1095
		break;
1096
 
1097
	case 51:	/* floating point load */
1098
		v = regoff(&p->from);
1099
		r = p->from.reg;
1100
		if(r == NREG)
1101
			r = o->param;
1102
		o1 = ofsr(p->as, p->to.reg, v, r, p->scond, p) | (1<<20);
1103
		break;
1104
 
1105
	case 52:	/* floating point store, long offset UGLY */
1106
		o1 = omvl(p, &p->to, REGTMP);
1107
		if(!o1)
1108
			break;
1109
		r = p->to.reg;
1110
		if(r == NREG)
1111
			r = o->param;
1112
		o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
1113
		o3 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
1114
		break;
1115
 
1116
	case 53:	/* floating point load, long offset UGLY */
1117
		o1 = omvl(p, &p->from, REGTMP);
1118
		if(!o1)
1119
			break;
1120
		r = p->from.reg;
1121
		if(r == NREG)
1122
			r = o->param;
1123
		o2 = oprrr(AADD, p->scond) | (REGTMP << 12) | (REGTMP << 16) | r;
1124
		o3 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
1125
		break;
1126
 
1127
	case 54:	/* floating point arith */
1128
		o1 = oprrr(p->as, p->scond);
1129
		if(p->from.type == D_FCONST) {
1130
			rf = chipfloat(p->from.ieee);
1131
			if(rf < 0){
1132
				diag("invalid floating-point immediate\n%P", p);
1133
				rf = 0;
1134
			}
1135
			rf |= (1<<3);
1136
		} else
1137
			rf = p->from.reg;
1138
		rt = p->to.reg;
1139
		r = p->reg;
1140
		if(p->to.type == D_NONE)
1141
			rt = 0;	/* CMP[FD] */
1142
		else if(o1 & (1<<15))
1143
			r = 0;	/* monadic */
1144
		else if(r == NREG)
1145
			r = rt;
1146
		o1 |= rf | (r<<16) | (rt<<12);
1147
		break;
1148
 
1149
	case 55:	/* floating point fix and float */
1150
		o1 = oprrr(p->as, p->scond);
1151
		rf = p->from.reg;
1152
		rt = p->to.reg;
1153
		if(p->to.type == D_NONE){
1154
			rt = 0;
1155
			diag("to.type==D_NONE (asm/fp)");
1156
		}
1157
		if(p->from.type == D_REG)
1158
			o1 |= (rf<<12) | (rt<<16);
1159
		else
1160
			o1 |= rf | (rt<<12);
1161
		break;
1162
 
1163
	/* old arm 7500 fp using coproc 1 (1<<8) */
1164
	case 56:	/* move to FP[CS]R */
1165
		o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
1166
		o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12);
1167
		break;
1168
 
1169
	case 57:	/* move from FP[CS]R */
1170
		o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4);
1171
		o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20);
1172
		break;
1173
	case 58:	/* movbu R,R */
1174
		o1 = oprrr(AAND, p->scond);
1175
		o1 |= immrot(0xff);
1176
		rt = p->to.reg;
1177
		r = p->from.reg;
1178
		if(p->to.type == D_NONE)
1179
			rt = 0;
1180
		if(r == NREG)
1181
			r = rt;
1182
		o1 |= (r<<16) | (rt<<12);
1183
		break;
1184
 
1185
	case 59:	/* movw/bu R<<I(R),R -> ldr indexed */
1186
		if(p->from.reg == NREG) {
1187
			if(p->as != AMOVW)
1188
				diag("byte MOV from shifter operand");
1189
			goto mov;
1190
		}
1191
		if(p->from.offset&(1<<4))
1192
			diag("bad shift in LDR");
1193
		o1 = olrr(p->from.offset, p->from.reg, p->to.reg, p->scond);
1194
		if(p->as == AMOVBU)
1195
			o1 |= 1<<22;
1196
		break;
1197
 
1198
	case 60:	/* movb R(R),R -> ldrsb indexed */
1199
		if(p->from.reg == NREG) {
1200
			diag("byte MOV from shifter operand");
1201
			goto mov;
1202
		}
1203
		if(p->from.offset&(~0xf))
1204
			diag("bad shift in LDRSB");
1205
		o1 = olhrr(p->from.offset, p->from.reg, p->to.reg, p->scond);
1206
		o1 ^= (1<<5)|(1<<6);
1207
		break;
1208
 
1209
	case 61:	/* movw/b/bu R,R<<[IR](R) -> str indexed */
1210
		if(p->to.reg == NREG)
1211
			diag("MOV to shifter operand");
1212
		o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond);
1213
		if(p->as == AMOVB || p->as == AMOVBU)
1214
			o1 |= 1<<22;
1215
		break;
1216
 
1217
	case 62:	/* case R -> movw	R<<2(PC),PC */
1218
		o1 = olrr(p->from.reg, REGPC, REGPC, p->scond);
1219
		o1 |= 2<<7;
1220
		break;
1221
 
1222
	case 63:	/* bcase */
1223
		if(p->cond != P) {
1224
			o1 = p->cond->pc;
1225
			if(dlm)
1226
				dynreloc(S, p->pc, 1);
1227
		}
1228
		break;
1229
 
1230
	/* reloc ops */
1231
	case 64:	/* mov/movb/movbu R,addr */
1232
		o1 = omvl(p, &p->to, REGTMP);
1233
		if(!o1)
1234
			break;
1235
		o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
1236
		break;
1237
 
1238
	case 65:	/* mov/movbu addr,R */
1239
	case 66:	/* movh/movhu/movb addr,R */
1240
		o1 = omvl(p, &p->from, REGTMP);
1241
		if(!o1)
1242
			break;
1243
		o2 = olr(0, REGTMP, p->to.reg, p->scond);
1244
		if(p->as == AMOVBU || p->as == AMOVB)
1245
			o2 |= 1<<22;
1246
		if(o->type == 65)
1247
			break;
1248
 
1249
		o3 = oprrr(ASLL, p->scond);
1250
 
1251
		if(p->as == AMOVBU || p->as == AMOVHU)
1252
			o4 = oprrr(ASRL, p->scond);
1253
		else
1254
			o4 = oprrr(ASRA, p->scond);
1255
 
1256
		r = p->to.reg;
1257
		o3 |= (r)|(r<<12);
1258
		o4 |= (r)|(r<<12);
1259
		if(p->as == AMOVB || p->as == AMOVBU) {
1260
			o3 |= (24<<7);
1261
			o4 |= (24<<7);
1262
		} else {
1263
			o3 |= (16<<7);
1264
			o4 |= (16<<7);
1265
		}
1266
		break;
1267
 
1268
	case 67:	/* movh/movhu R,addr -> sb, sb */
1269
		o1 = omvl(p, &p->to, REGTMP);
1270
		if(!o1)
1271
			break;
1272
		o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
1273
 
1274
		o3 = oprrr(ASRL, p->scond);
1275
		o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12);
1276
		o3 |= (1<<6);	/* ROR 8 */
1277
 
1278
		o4 = oprrr(AADD, p->scond);
1279
		o4 |= (REGTMP << 12) | (REGTMP << 16);
1280
		o4 |= immrot(1);
1281
 
1282
		o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond);
1283
 
1284
		o6 = oprrr(ASRL, p->scond);
1285
		o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12);
1286
		o6 |= (1<<6);	/* ROL 8 */
1287
		break;
1288
 
1289
	case 68:	/* floating point store -> ADDR */
1290
		o1 = omvl(p, &p->to, REGTMP);
1291
		if(!o1)
1292
			break;
1293
		o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p);
1294
		break;
1295
 
1296
	case 69:	/* floating point load <- ADDR */
1297
		o1 = omvl(p, &p->from, REGTMP);
1298
		if(!o1)
1299
			break;
1300
		o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20);
1301
		break;
1302
 
1303
	/* ArmV4 ops: */
1304
	case 70:	/* movh/movhu R,O(R) -> strh */
1305
		aclass(&p->to);
1306
		r = p->to.reg;
1307
		if(r == NREG)
1308
			r = o->param;
1309
		o1 = oshr(p->from.reg, instoffset, r, p->scond);
1310
		break;	
1311
	case 71:	/* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
1312
		aclass(&p->from);
1313
		r = p->from.reg;
1314
		if(r == NREG)
1315
			r = o->param;
1316
		o1 = olhr(instoffset, r, p->to.reg, p->scond);
1317
		if(p->as == AMOVB)
1318
			o1 ^= (1<<5)|(1<<6);
1319
		else if(p->as == AMOVH)
1320
			o1 ^= (1<<6);
1321
		break;
1322
	case 72:	/* movh/movhu R,L(R) -> strh */
1323
		o1 = omvl(p, &p->to, REGTMP);
1324
		if(!o1)
1325
			break;
1326
		r = p->to.reg;
1327
		if(r == NREG)
1328
			r = o->param;
1329
		o2 = oshrr(p->from.reg, REGTMP,r, p->scond);
1330
		break;	
1331
	case 73:	/* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
1332
		o1 = omvl(p, &p->from, REGTMP);
1333
		if(!o1)
1334
			break;
1335
		r = p->from.reg;
1336
		if(r == NREG)
1337
			r = o->param;
1338
		o2 = olhrr(REGTMP, r, p->to.reg, p->scond);
1339
		if(p->as == AMOVB)
1340
			o2 ^= (1<<5)|(1<<6);
1341
		else if(p->as == AMOVH)
1342
			o2 ^= (1<<6);
1343
		break;
1344
 
1345
	/* VFP ops: */
1346
	case 74:	/* vfp floating point arith */
1347
		o1 = opvfprrr(p->as, p->scond);
1348
		rf = p->from.reg;
1349
		if(p->from.type == D_FCONST) {
1350
			diag("invalid floating-point immediate\n%P", p);
1351
			rf = 0;
1352
		}
1353
		rt = p->to.reg;
1354
		r = p->reg;
1355
		if(r == NREG)
1356
			r = rt;
1357
		o1 |= rt<<12;
1358
		if(((o1>>20)&0xf) == 0xb)
1359
			o1 |= rf<<0;
1360
		else
1361
			o1 |= r<<16 | rf<<0;
1362
		break;
1363
	case 75:	/* vfp floating point compare */
1364
		o1 = opvfprrr(p->as, p->scond);
1365
		rf = p->from.reg;
1366
		if(p->from.type == D_FCONST) {
1367
			if(p->from.ieee->h != 0 || p->from.ieee->l != 0)
1368
				diag("invalid floating-point immediate\n%P", p);
1369
			o1 |= 1<<16;
1370
			rf = 0;
1371
		}
1372
		rt = p->reg;
1373
		o1 |= rt<<12 | rf<<0;
1374
		o2 = 0x0ef1fa10;	/* MRS APSR_nzcv, FPSCR */
1375
		o2 |= (p->scond & C_SCOND) << 28;
1376
		break;
1377
	case 76:	/* vfp floating point fix and float */
1378
		o1 = opvfprrr(p->as, p->scond);
1379
		rf = p->from.reg;
1380
		rt = p->to.reg;
1381
		if(p->from.type == D_REG) {
1382
			o2 = o1 | rt<<12 | rt<<0;
1383
			o1 = 0x0e000a10;	/* VMOV F,R */
1384
			o1 |= (p->scond & C_SCOND) << 28 | rt<<16 | rf<<12;
1385
		} else {
1386
			o1 |= FREGTMP<<12 | rf<<0;
1387
			o2 = 0x0e100a10;	/* VMOV R,F */
1388
			o2 |= (p->scond & C_SCOND) << 28 | FREGTMP<<16 | rt<<12;
1389
		}
1390
		break;
1391
	}
1392
 
1393
	if(debug['a'] > 1)
1394
		Bprint(&bso, "%2d ", o->type);
1395
 
1396
	v = p->pc;
1397
	switch(o->size) {
1398
	default:
1399
		if(debug['a'])
1400
			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
1401
		break;
1402
	case 4:
1403
		if(debug['a'])
1404
			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
1405
		lputl(o1);
1406
		break;
1407
	case 8:
1408
		if(debug['a'])
1409
			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
1410
		lputl(o1);
1411
		lputl(o2);
1412
		break;
1413
	case 12:
1414
		if(debug['a'])
1415
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
1416
		lputl(o1);
1417
		lputl(o2);
1418
		lputl(o3);
1419
		break;
1420
	case 16:
1421
		if(debug['a'])
1422
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
1423
				v, o1, o2, o3, o4, p);
1424
		lputl(o1);
1425
		lputl(o2);
1426
		lputl(o3);
1427
		lputl(o4);
1428
		break;
1429
	case 20:
1430
		if(debug['a'])
1431
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1432
				v, o1, o2, o3, o4, o5, p);
1433
		lputl(o1);
1434
		lputl(o2);
1435
		lputl(o3);
1436
		lputl(o4);
1437
		lputl(o5);
1438
		break;
1439
	case 24:
1440
		if(debug['a'])
1441
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1442
				v, o1, o2, o3, o4, o5, o6, p);
1443
		lputl(o1);
1444
		lputl(o2);
1445
		lputl(o3);
1446
		lputl(o4);
1447
		lputl(o5);
1448
		lputl(o6);
1449
		break;
1450
	}
1451
}
1452
 
1453
long
1454
oprrr(int a, int sc)
1455
{
1456
	long o;
1457
 
1458
	o = (sc & C_SCOND) << 28;
1459
	if(sc & C_SBIT)
1460
		o |= 1 << 20;
1461
	if(sc & (C_PBIT|C_WBIT))
1462
		diag(".P/.W on dp instruction");
1463
	switch(a) {
1464
	case AMULU:
1465
	case AMUL:	return o | (0x0<<21) | (0x9<<4);
1466
	case AMULA:	return o | (0x1<<21) | (0x9<<4);
1467
	case AMULLU:	return o | (0x4<<21) | (0x9<<4);
1468
	case AMULL:	return o | (0x6<<21) | (0x9<<4);
1469
	case AMULALU:	return o | (0x5<<21) | (0x9<<4);
1470
	case AMULAL:	return o | (0x7<<21) | (0x9<<4);
1471
	case AAND:	return o | (0x0<<21);
1472
	case AEOR:	return o | (0x1<<21);
1473
	case ASUB:	return o | (0x2<<21);
1474
	case ARSB:	return o | (0x3<<21);
1475
	case AADD:	return o | (0x4<<21);
1476
	case AADC:	return o | (0x5<<21);
1477
	case ASBC:	return o | (0x6<<21);
1478
	case ARSC:	return o | (0x7<<21);
1479
	case ATST:	return o | (0x8<<21) | (1<<20);
1480
	case ATEQ:	return o | (0x9<<21) | (1<<20);
1481
	case ACMP:	return o | (0xa<<21) | (1<<20);
1482
	case ACMN:	return o | (0xb<<21) | (1<<20);
1483
	case AORR:	return o | (0xc<<21);
1484
	case AMOVW:	return o | (0xd<<21);
1485
	case ABIC:	return o | (0xe<<21);
1486
	case AMVN:	return o | (0xf<<21);
1487
	case ASLL:	return o | (0xd<<21) | (0<<5);
1488
	case ASRL:	return o | (0xd<<21) | (1<<5);
1489
	case ASRA:	return o | (0xd<<21) | (2<<5);
1490
	case ASWI:	return o | (0xf<<24);
1491
 
1492
	/* old arm 7500 fp using coproc 1 (1<<8) */
1493
	case AADDD:	return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7);
1494
	case AADDF:	return o | (0xe<<24) | (0x0<<20) | (1<<8);
1495
	case AMULD:	return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7);
1496
	case AMULF:	return o | (0xe<<24) | (0x1<<20) | (1<<8);
1497
	case ASUBD:	return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7);
1498
	case ASUBF:	return o | (0xe<<24) | (0x2<<20) | (1<<8);
1499
	case ADIVD:	return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7);
1500
	case ADIVF:	return o | (0xe<<24) | (0x4<<20) | (1<<8);
1501
	case ACMPD:
1502
	case ACMPF:	return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4);	/* arguably, ACMPF should expand to RNDF, CMPD */
1503
 
1504
	case AMOVF:
1505
	case AMOVDF:	return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8);
1506
	case AMOVD:
1507
	case AMOVFD:	return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7);
1508
 
1509
	case AMOVWF:	return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4);
1510
	case AMOVWD:	return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7);
1511
	case AMOVFW:	return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4);
1512
	case AMOVDW:	return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7);
1513
	}
1514
	diag("bad rrr %d", a);
1515
	prasm(curp);
1516
	return 0;
1517
}
1518
 
1519
long
1520
opvfprrr(int a, int sc)
1521
{
1522
	long o;
1523
 
1524
	o = (sc & C_SCOND) << 28;
1525
	if(sc & (C_SBIT|C_PBIT|C_WBIT))
1526
		diag(".S/.P/.W on vfp instruction");
1527
	o |= 0xe<<24;
1528
	switch(a) {
1529
	case AMOVWD:	return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x8<<16 | 1<<7;
1530
	case AMOVWF:	return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x8<<16 | 1<<7;
1531
	case AMOVDW:	return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0xD<<16 | 1<<7;
1532
	case AMOVFW:	return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0xD<<16 | 1<<7;
1533
	case AMOVFD:	return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x7<<16 | 1<<7;
1534
	case AMOVDF:	return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x7<<16 | 1<<7;
1535
	case AMOVF:	return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x0<<16 | 0<<7;
1536
	case AMOVD:	return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x0<<16 | 0<<7;
1537
	case ACMPF:	return o | 0xa<<8 | 0xb<<20 | 1<<6 | 0x4<<16 | 0<<7;
1538
	case ACMPD:	return o | 0xb<<8 | 0xb<<20 | 1<<6 | 0x4<<16 | 0<<7;
1539
	case AADDF:	return o | 0xa<<8 | 0x3<<20;
1540
	case AADDD:	return o | 0xb<<8 | 0x3<<20;
1541
	case ASUBF:	return o | 0xa<<8 | 0x3<<20 | 1<<6;
1542
	case ASUBD:	return o | 0xb<<8 | 0x3<<20 | 1<<6;
1543
	case AMULF:	return o | 0xa<<8 | 0x2<<20;
1544
	case AMULD:	return o | 0xb<<8 | 0x2<<20;
1545
	case ADIVF:	return o | 0xa<<8 | 0x8<<20;
1546
	case ADIVD:	return o | 0xb<<8 | 0x8<<20;
1547
	}
1548
	diag("bad vfp rrr %d", a);
1549
	prasm(curp);
1550
	return 0;
1551
}
1552
 
1553
long
1554
opbra(int a, int sc)
1555
{
1556
 
1557
	if(sc & (C_SBIT|C_PBIT|C_WBIT))
1558
		diag(".S/.P/.W on bra instruction");
1559
	sc &= C_SCOND;
1560
	if(a == ABL)
1561
		return (sc<<28)|(0x5<<25)|(0x1<<24);
1562
	if(sc != 0xe)
1563
		diag(".COND on bcond instruction");
1564
	switch(a) {
1565
	case ABEQ:	return (0x0<<28)|(0x5<<25);
1566
	case ABNE:	return (0x1<<28)|(0x5<<25);
1567
	case ABCS:	return (0x2<<28)|(0x5<<25);
1568
	case ABHS:	return (0x2<<28)|(0x5<<25);
1569
	case ABCC:	return (0x3<<28)|(0x5<<25);
1570
	case ABLO:	return (0x3<<28)|(0x5<<25);
1571
	case ABMI:	return (0x4<<28)|(0x5<<25);
1572
	case ABPL:	return (0x5<<28)|(0x5<<25);
1573
	case ABVS:	return (0x6<<28)|(0x5<<25);
1574
	case ABVC:	return (0x7<<28)|(0x5<<25);
1575
	case ABHI:	return (0x8<<28)|(0x5<<25);
1576
	case ABLS:	return (0x9<<28)|(0x5<<25);
1577
	case ABGE:	return (0xa<<28)|(0x5<<25);
1578
	case ABLT:	return (0xb<<28)|(0x5<<25);
1579
	case ABGT:	return (0xc<<28)|(0x5<<25);
1580
	case ABLE:	return (0xd<<28)|(0x5<<25);
1581
	case AB:	return (0xe<<28)|(0x5<<25);
1582
	}
1583
	diag("bad bra %A", a);
1584
	prasm(curp);
1585
	return 0;
1586
}
1587
 
1588
long
1589
olr(long v, int b, int r, int sc)
1590
{
1591
	long o;
1592
 
1593
	if(sc & C_SBIT)
1594
		diag(".S on LDR/STR instruction");
1595
	o = (sc & C_SCOND) << 28;
1596
	if(!(sc & C_PBIT))
1597
		o |= 1 << 24;
1598
	if(!(sc & C_UBIT))
1599
		o |= 1 << 23;
1600
	if(sc & C_WBIT)
1601
		o |= 1 << 21;
1602
	o |= (0x1<<26) | (1<<20);
1603
	if(v < 0) {
1604
		v = -v;
1605
		o ^= 1 << 23;
1606
	}
1607
	if(v >= (1<<12))
1608
		diag("literal span too large: %ld (R%d)\n%P", v, b, PP);
1609
	o |= v;
1610
	o |= b << 16;
1611
	o |= r << 12;
1612
	return o;
1613
}
1614
 
1615
long
1616
olhr(long v, int b, int r, int sc)
1617
{
1618
	long o;
1619
 
1620
	if(sc & C_SBIT)
1621
		diag(".S on LDRH/STRH instruction");
1622
	o = (sc & C_SCOND) << 28;
1623
	if(!(sc & C_PBIT))
1624
		o |= 1 << 24;
1625
	if(sc & C_WBIT)
1626
		o |= 1 << 21;
1627
	o |= (1<<23) | (1<<20)|(0xb<<4);
1628
	if(v < 0) {
1629
		v = -v;
1630
		o ^= 1 << 23;
1631
	}
1632
	if(v >= (1<<8))
1633
		diag("literal span too large: %ld (R%d)\n%P", v, b, PP);
1634
	o |= (v&0xf)|((v>>4)<<8)|(1<<22);
1635
	o |= b << 16;
1636
	o |= r << 12;
1637
	return o;
1638
}
1639
 
1640
long
1641
osr(int a, int r, long v, int b, int sc)
1642
{
1643
	long o;
1644
 
1645
	o = olr(v, b, r, sc) ^ (1<<20);
1646
	if(a != AMOVW)
1647
		o |= 1<<22;
1648
	return o;
1649
}
1650
 
1651
long
1652
oshr(int r, long v, int b, int sc)
1653
{
1654
	long o;
1655
 
1656
	o = olhr(v, b, r, sc) ^ (1<<20);
1657
	return o;
1658
}
1659
 
1660
 
1661
long
1662
osrr(int r, int i, int b, int sc)
1663
{
1664
 
1665
	return olr(i, b, r, sc) ^ ((1<<25) | (1<<20));
1666
}
1667
 
1668
long
1669
oshrr(int r, int i, int b, int sc)
1670
{
1671
	return olhr(i, b, r, sc) ^ ((1<<22) | (1<<20));
1672
}
1673
 
1674
long
1675
olrr(int i, int b, int r, int sc)
1676
{
1677
 
1678
	return olr(i, b, r, sc) ^ (1<<25);
1679
}
1680
 
1681
long
1682
olhrr(int i, int b, int r, int sc)
1683
{
1684
	return olhr(i, b, r, sc) ^ (1<<22);
1685
}
1686
 
1687
long
1688
ovfpmem(int a, int r, long v, int b, int sc, Prog *p)
1689
{
1690
	long o;
1691
 
1692
	if(sc & (C_SBIT|C_PBIT|C_WBIT))
1693
		diag(".S/.P/.W on VLDR/VSTR instruction");
1694
	o = (sc & C_SCOND) << 28;
1695
	o |= 0xd<<24 | (1<<23);
1696
	if(v < 0) {
1697
		v = -v;
1698
		o ^= 1 << 23;
1699
	}
1700
	if(v & 3)
1701
		diag("odd offset for floating point op: %ld\n%P", v, p);
1702
	else if(v >= (1<<10))
1703
		diag("literal span too large: %ld\n%P", v, p);
1704
	o |= (v>>2) & 0xFF;
1705
	o |= b << 16;
1706
	o |= r << 12;
1707
	switch(a) {
1708
	default:
1709
		diag("bad fst %A", a);
1710
	case AMOVD:
1711
		o |= 0xb<<8;
1712
		break;
1713
	case AMOVF:
1714
		o |= 0xa<<8;
1715
		break;
1716
	}
1717
	return o;
1718
}
1719
 
1720
long
1721
ofsr(int a, int r, long v, int b, int sc, Prog *p)
1722
{
1723
	long o;
1724
 
1725
	if(vfp)
1726
		return ovfpmem(a, r, v, b, sc, p);
1727
	if(sc & C_SBIT)
1728
		diag(".S on FLDR/FSTR instruction");
1729
	o = (sc & C_SCOND) << 28;
1730
	if(!(sc & C_PBIT))
1731
		o |= 1 << 24;
1732
	if(sc & C_WBIT)
1733
		o |= 1 << 21;
1734
	o |= (6<<25) | (1<<24) | (1<<23);
1735
	if(v < 0) {
1736
		v = -v;
1737
		o ^= 1 << 23;
1738
	}
1739
	if(v & 3)
1740
		diag("odd offset for floating point op: %ld\n%P", v, p);
1741
	else if(v >= (1<<10))
1742
		diag("literal span too large: %ld\n%P", v, p);
1743
	o |= (v>>2) & 0xFF;
1744
	o |= b << 16;
1745
	o |= r << 12;
1746
	o |= 1 << 8;
1747
 
1748
	switch(a) {
1749
	default:
1750
		diag("bad fst %A", a);
1751
	case AMOVD:
1752
		o |= 1<<15;
1753
	case AMOVF:
1754
		break;
1755
	}
1756
	return o;
1757
}
1758
 
1759
long
1760
omvl(Prog *p, Adr *a, int dr)
1761
{	
1762
	long v, o1;
1763
	if(!p->cond) {
1764
		aclass(a);
1765
		v = immrot(~instoffset);
1766
		if(v == 0) {
1767
			diag("missing literal");
1768
			prasm(p);
1769
			return 0;
1770
		}
1771
		o1 = oprrr(AMVN, p->scond&C_SCOND);
1772
		o1 |= v;
1773
		o1 |= dr << 12;
1774
	} else {
1775
		v = p->cond->pc - p->pc - 8;
1776
		o1 = olr(v, REGPC, dr, p->scond&C_SCOND);
1777
	}
1778
	return o1;
1779
}
1780
 
1781
static Ieee chipfloats[] = {
1782
	{0x00000000, 0x00000000}, /* 0 */
1783
	{0x00000000, 0x3ff00000}, /* 1 */
1784
	{0x00000000, 0x40000000}, /* 2 */
1785
	{0x00000000, 0x40080000}, /* 3 */
1786
	{0x00000000, 0x40100000}, /* 4 */
1787
	{0x00000000, 0x40140000}, /* 5 */
1788
	{0x00000000, 0x3fe00000}, /* .5 */
1789
	{0x00000000, 0x40240000}, /* 10 */
1790
};
1791
 
1792
int
1793
chipfloat(Ieee *e)
1794
{
1795
	Ieee *p;
1796
	int n;
1797
 
1798
	if(vfp)
1799
		return -1;
1800
	for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){
1801
		p = &chipfloats[n];
1802
		if(p->l == e->l && p->h == e->h)
1803
			return n;
1804
	}
1805
	return -1;
1806
}