Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <mach.h>
5
#include "arm.h"
6
 
7
static	int	dummy;
8
static	char*	shtype[4] =
9
{
10
	"<<",
11
	">>",
12
	"->",
13
	"@>",
14
};
15
static	char*	cond[16] =
16
{
17
	".EQ",	".NE",	".HS",	".LO",
18
	".MI",	".PL",	".VS",	".VC",
19
	".HI",	".LS",	".GE",	".LT",
20
	".GT",	".LE",	"",	".NO",
21
};
22
 
23
void	Idp0(ulong);
24
void	Idp1(ulong);
25
void	Idp2(ulong);
26
void	Idp3(ulong);
27
 
28
void	Imul(ulong);
29
void	Imula(ulong);
30
void	Imull(ulong);
31
 
32
void	Iswap(ulong);
33
void	Imem1(ulong);
34
void	Imem2(ulong);
35
void	Ilsm(ulong inst);
36
 
37
void	Ib(ulong);
38
void	Ibl(ulong);
39
 
40
void	Ssyscall(ulong);
41
 
42
Inst itab[] =
43
{
44
	{ Idp0,		"AND",	Iarith },	/* 00 - r,r,r */
45
	{ Idp0,		"EOR",	Iarith },	/* 01 */
46
	{ Idp0,		"SUB",	Iarith },	/* 02 */
47
	{ Idp0,		"RSB",	Iarith },	/* 03 */
48
	{ Idp0,		"ADD",	Iarith },	/* 04 */
49
	{ Idp0,		"ADC",	Iarith },	/* 05 */
50
	{ Idp0,		"SBC",	Iarith },	/* 06 */
51
	{ Idp0,		"RSC",	Iarith },	/* 07 */
52
	{ Idp0,		"TST",	Iarith },	/* 08 */
53
	{ Idp0,		"TEQ",	Iarith },	/* 09 */
54
 
55
	{ Idp0,		"CMP",	Iarith },	/* 10 */
56
	{ Idp0,		"CMN",	Iarith },	/* 11 */
57
	{ Idp0,		"ORR",	Iarith },	/* 12 */
58
	{ Idp0,		"MOV",	Iarith },	/* 13 */
59
	{ Idp0,		"BIC",	Iarith },	/* 14 */
60
	{ Idp0,		"MVN",	Iarith },	/* 15 */
61
	{ Idp1,		"AND",	Iarith },	/* 16 */
62
	{ Idp1,		"EOR",	Iarith },	/* 17 */
63
	{ Idp1,		"SUB",	Iarith },	/* 18 */
64
	{ Idp1,		"RSB",	Iarith },	/* 19 */
65
 
66
	{ Idp1,		"ADD",	Iarith },	/* 20 */
67
	{ Idp1,		"ADC",	Iarith },	/* 21 */
68
	{ Idp1,		"SBC",	Iarith },	/* 22 */
69
	{ Idp1,		"RSC",	Iarith },	/* 23 */
70
	{ Idp1,		"TST",	Iarith },	/* 24 */
71
	{ Idp1,		"TEQ",	Iarith },	/* 25 */
72
	{ Idp1,		"CMP",	Iarith },	/* 26 */
73
	{ Idp1,		"CMN",	Iarith },	/* 27 */
74
	{ Idp1,		"ORR",	Iarith },	/* 28 */
75
	{ Idp1,		"MOV",	Iarith },	/* 29 */
76
 
77
	{ Idp1,		"BIC",	Iarith },	/* 30 */
78
	{ Idp1,		"MVN",	Iarith },	/* 31 */
79
	{ Idp2,		"AND",	Iarith },	/* 32 */
80
	{ Idp2,		"EOR",	Iarith },	/* 33 */
81
	{ Idp2,		"SUB",	Iarith },	/* 34 */
82
	{ Idp2,		"RSB",	Iarith },	/* 35 */
83
	{ Idp2,		"ADD",	Iarith },	/* 36 */
84
	{ Idp2,		"ADC",	Iarith },	/* 37 */
85
	{ Idp2,		"SBC",	Iarith },	/* 38 */
86
	{ Idp2,		"RSC",	Iarith },	/* 39 */
87
 
88
	{ Idp2,		"TST",	Iarith },	/* 40 */
89
	{ Idp2,		"TEQ",	Iarith },	/* 41 */
90
	{ Idp2,		"CMP",	Iarith },	/* 42 */
91
	{ Idp2,		"CMN",	Iarith },	/* 43 */
92
	{ Idp2,		"ORR",	Iarith },	/* 44 */
93
	{ Idp2,		"MOV",	Iarith },	/* 45 */
94
	{ Idp2,		"BIC",	Iarith },	/* 46 */
95
	{ Idp2,		"MVN",	Iarith },	/* 47 */
96
	{ Idp3,		"AND",	Iarith },	/* 48 - i,r,r */
97
	{ Idp3,		"EOR",	Iarith },	/* 49 */
98
 
99
	{ Idp3,		"SUB",	Iarith },	/* 50 */
100
	{ Idp3,		"RSB",	Iarith },	/* 51 */
101
	{ Idp3,		"ADD",	Iarith },	/* 52 */
102
	{ Idp3,		"ADC",	Iarith },	/* 53 */
103
	{ Idp3,		"SBC",	Iarith },	/* 54 */
104
	{ Idp3,		"RSC",	Iarith },	/* 55 */
105
	{ Idp3,		"TST",	Iarith },	/* 56 */
106
	{ Idp3,		"TEQ",	Iarith },	/* 57 */
107
	{ Idp3,		"CMP",	Iarith },	/* 58 */
108
	{ Idp3,		"CMN",	Iarith },	/* 59 */
109
 
110
	{ Idp3,		"ORR",	Iarith },	/* 60 */
111
	{ Idp3,		"MOV",	Iarith },	/* 61 */
112
	{ Idp3,		"BIC",	Iarith },	/* 62 */
113
	{ Idp3,		"MVN",	Iarith },	/* 63 */
114
	{ Imul,		"MUL",	Iarith },	/* 64 */
115
	{ Imula,	"MULA",	Iarith },	/* 65 */
116
 
117
	{ Iswap,	"SWPW",	Imem },	/* 66 */
118
	{ Iswap,	"SWPBU",	Imem },	/* 67 */
119
 
120
	{ Imem2,	"MOV",	Imem },	/* 68 load/store h/sb */
121
	{ Imem2,	"MOV",	Imem },	/* 69 */
122
	{ Imem2,	"MOV",	Imem },	/* 70 */
123
	{ Imem2,	"MOV",	Imem },	/* 71 */
124
 
125
	{ Imem1,	"MOVW",	Imem },	/* 72 load/store w/ub i,r */
126
	{ Imem1,	"MOVB",	Imem },	/* 73 */
127
	{ Imem1,	"MOVW",	Imem },	/* 74 */
128
	{ Imem1,	"MOVB",	Imem },	/* 75 */
129
	{ Imem1,	"MOVW",	Imem },	/* 76 load/store r,r */
130
	{ Imem1,	"MOVB",	Imem },	/* 77 */
131
	{ Imem1,	"MOVW",	Imem },	/* 78 */
132
	{ Imem1,	"MOVB",	Imem },	/* 79 */
133
 
134
	{ Ilsm,		"LDM",	Imem },	/* 80 block move r,r */
135
	{ Ilsm,		"STM",	Imem },	/* 81 */
136
	{ Ib,		"B",	Ibranch },		/* 82 branch */
137
	{ Ibl,		"BL",	Ibranch },		/* 83 */
138
	{ Ssyscall,	"SWI",	Isyscall },	/* 84 co processor */
139
	{ undef,	"undef" },	/* 85 */
140
	{ undef,	"undef" },	/* 86 */
141
	{ undef,	"undef"  },	/* 87 */
142
	{ Imull,	"MULLU",	Iarith },	/* 88 */
143
	{ Imull,	"MULALU",	Iarith },	/* 89 */
144
	{ Imull,	"MULL",	Iarith  },	/* 90 */
145
	{ Imull,	"MULAL",	Iarith  },	/* 91 */
146
	{ undef,	"undef"  },	/* 92 */
147
 
148
	{ 0 }
149
};
150
 
151
int
152
runcmp(void)
153
{
154
	switch(reg.cond) {
155
	case 0x0:	/* eq */	return (reg.cc1 == reg.cc2);
156
	case 0x1:	/* ne */	return (reg.cc1 != reg.cc2);
157
	case 0x2:	/* hs */	return ((ulong)reg.cc1 >= (ulong)reg.cc2);
158
	case 0x3:	/* lo */	return ((ulong)reg.cc1 < (ulong)reg.cc2);
159
	case 0x4:	/* mi */	return (reg.cc1 - reg.cc2 < 0);
160
	case 0x5:	/* pl */	return (reg.cc1 - reg.cc2 >= 0);
161
	case 0x8:	/* hi */	return ((ulong)reg.cc1 > (ulong)reg.cc2);
162
	case 0x9:	/* ls */	return ((ulong)reg.cc1 <= (ulong)reg.cc2);
163
	case 0xa:	/* ge */	return (reg.cc1 >= reg.cc2);
164
	case 0xb:	/* lt */	return (reg.cc1 < reg.cc2);
165
	case 0xc:	/* gt */	return (reg.cc1 > reg.cc2);
166
	case 0xd:	/* le */	return (reg.cc1 <= reg.cc2);
167
	case 0xe:	/* al */	return 1;
168
	case 0xf:	/* nv */	return 0;
169
	default:
170
		Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
171
			reg.cond, reg.cc1, reg.cc2);
172
		undef(reg.ir);
173
		return 0;
174
	}
175
}
176
 
177
int
178
runteq(void)
179
{
180
	long res = reg.cc1 ^ reg.cc2;
181
	switch(reg.cond) {
182
	case 0x0:	/* eq */	return res == 0;
183
	case 0x1:	/* ne */	return res != 0;
184
	case 0x4:	/* mi */	return (res & SIGNBIT) != 0;
185
	case 0x5:	/* pl */	return (res & SIGNBIT) == 0;
186
	case 0xe:	/* al */	return 1;
187
	case 0xf:	/* nv */	return 0;
188
	default:
189
		Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
190
			reg.cond, reg.cc1, reg.cc2);
191
		undef(reg.ir);
192
		return 0;
193
	}
194
}
195
 
196
int
197
runtst(void)
198
{
199
	long res = reg.cc1 & reg.cc2;
200
	switch(reg.cond) {
201
	case 0x0:	/* eq */	return res == 0;
202
	case 0x1:	/* ne */	return res != 0;
203
	case 0x4:	/* mi */	return (res & SIGNBIT) != 0;
204
	case 0x5:	/* pl */	return (res & SIGNBIT) == 0;
205
	case 0xe:	/* al */	return 1;
206
	case 0xf:	/* nv */	return 0;
207
	default:
208
		Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
209
			reg.cond, reg.cc1, reg.cc2);
210
		undef(reg.ir);
211
		return 0;
212
	}
213
}
214
 
215
void
216
run(void)
217
{
218
	int execute;
219
 
220
	do {
221
		if(trace)
222
			Bflush(bioout);
223
		reg.ar = reg.r[REGPC];
224
		reg.ir = ifetch(reg.ar);
225
		reg.class = armclass(reg.ir);
226
		reg.ip = &itab[reg.class];
227
		reg.cond = (reg.ir>>28) & 0xf;
228
		switch(reg.compare_op) {
229
		case CCcmp:
230
			execute = runcmp();
231
			break;
232
		case CCteq:
233
			execute = runteq();
234
			break;
235
		case CCtst:
236
			execute = runtst();
237
			break;
238
		default:
239
			Bprint(bioout, "unimplemented compare operation %x\n",
240
				reg.compare_op);
241
			return;
242
		}
243
 
244
		if(execute) {
245
			reg.ip->count++;
246
			(*reg.ip->func)(reg.ir);
247
		} else {
248
			if(trace)
249
				itrace("%s%s	IGNORED",
250
					reg.ip->name, cond[reg.cond]);
251
		}
252
		reg.r[REGPC] += 4;
253
		if(bplist)
254
			brkchk(reg.r[REGPC], Instruction);
255
	} while(--count);
256
}
257
 
258
void
259
undef(ulong inst)
260
{
261
	Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n",
262
		reg.r[REGPC], inst, reg.class);
263
	longjmp(errjmp, 0);
264
}
265
 
266
long
267
shift(long v, int st, int sc, int isreg)
268
{
269
	if(sc == 0) {
270
		switch(st) {
271
		case 0:	/* logical left */
272
			reg.cout = reg.cbit;
273
			break;
274
		case 1:	/* logical right */
275
			reg.cout = (v >> 31) & 1;
276
			break;
277
		case 2:	/* arith right */
278
			reg.cout = reg.cbit;
279
			break;
280
		case 3:	/* rotate right */
281
			if(isreg) {
282
				reg.cout = reg.cbit;
283
			}
284
			else {
285
				reg.cout = v & 1;
286
				v = ((ulong)v >> 1) | (reg.cbit << 31);
287
			}
288
		}
289
	}
290
	else {
291
		switch(st) {
292
		case 0:	/* logical left */
293
			reg.cout = (v >> (32 - sc)) & 1;
294
			v = v << sc;
295
			break;
296
		case 1:	/* logical right */
297
			reg.cout = (v >> (sc - 1)) & 1;
298
			v = (ulong)v >> sc;
299
			break;
300
		case 2:	/* arith right */
301
			if(sc >= 32) {
302
				reg.cout = (v >> 31) & 1;
303
				if(reg.cout)
304
					v = 0xFFFFFFFF;
305
				else
306
					v = 0;
307
			}
308
			else {
309
				reg.cout = (v >> (sc - 1)) & 1;
310
				v = (long)v >> sc;
311
			}
312
			break;
313
		case 3:	/* rotate right */
314
			reg.cout = (v >> (sc - 1)) & 1;
315
			v = (v << (32-sc)) | ((ulong)v >> sc);
316
			break;
317
		}
318
	}
319
	return v;
320
}
321
 
322
void
323
dpex(long inst, long o1, long o2, int rd)
324
{
325
	int cbit;
326
 
327
	cbit = 0;
328
	switch((inst>>21) & 0xf) {
329
	case  0:	/* and */
330
		reg.r[rd] = o1 & o2;
331
		cbit = 1;
332
		break;
333
	case  1:	/* eor */
334
		reg.r[rd] = o1 ^ o2;
335
		cbit = 1;
336
		break;
337
	case  2:	/* sub */
338
		reg.r[rd] = o1 - o2;
339
	case 10:	/* cmp */
340
		if(inst & Sbit) {
341
			reg.cc1 = o1;
342
			reg.cc2 = o2;
343
			reg.compare_op = CCcmp;
344
		}
345
		return;
346
	case  3:	/* rsb */
347
		reg.r[rd] = o2 - o1;
348
		if(inst & Sbit) {
349
			reg.cc1 = o2;
350
			reg.cc2 = o1;
351
			reg.compare_op = CCcmp;
352
		}
353
		return;
354
	case  4:	/* add */
355
		if(calltree && rd == REGPC && o2 == 0) {
356
			Symbol s;
357
 
358
			findsym(o1 + o2, CTEXT, &s);
359
			Bprint(bioout, "%8lux return to %lux %s r0=%lux\n",
360
						reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]);
361
		}
362
		reg.r[rd] = o1 + o2;
363
		if(inst & Sbit) {
364
			if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32))
365
				reg.cbit = 1;
366
			else
367
				reg.cbit = 0;
368
			reg.cc1 = o2;
369
			reg.cc2 = -o1;
370
			reg.compare_op = CCcmp;
371
		}
372
		return;
373
	case  5:	/* adc */
374
	case  6:	/* sbc */
375
	case  7:	/* rsc */
376
		undef(inst);
377
	case  8:	/* tst */
378
		if(inst & Sbit) {
379
			reg.cc1 = o1;
380
			reg.cc2 = o2;
381
			reg.compare_op = CCtst;
382
		}
383
		return;
384
	case  9:	/* teq */
385
		if(inst & Sbit) {
386
			reg.cc1 = o1;
387
			reg.cc2 = o2;
388
			reg.compare_op = CCteq;
389
		}
390
		return;
391
	case 11:	/* cmn */
392
		if(inst & Sbit) {
393
			reg.cc1 = o1;
394
			reg.cc2 = -o2;
395
			reg.compare_op = CCcmp;
396
		}
397
		return;
398
	case 12:	/* orr */
399
		reg.r[rd] = o1 | o2;
400
		cbit = 1;
401
		break;
402
	case 13:	/* mov */
403
		reg.r[rd] = o2;
404
		cbit = 1;
405
		break;
406
	case 14:	/* bic */
407
		reg.r[rd] = o1 & ~o2;
408
		cbit = 1;
409
		break;
410
	case 15:	/* mvn */
411
		reg.r[rd] = ~o2;
412
		cbit = 1;
413
		break;
414
	}
415
	if(inst & Sbit) {
416
		if(cbit)
417
			reg.cbit = reg.cout;
418
		reg.cc1 = reg.r[rd];
419
		reg.cc2 = 0;
420
		reg.compare_op = CCcmp;
421
	}
422
}
423
 
424
/*
425
 * data processing instruction R,R,R
426
 */
427
void
428
Idp0(ulong inst)
429
{
430
	int rn, rd, rm;
431
	long o1, o2;
432
 
433
	rn = (inst>>16) & 0xf;
434
	rd = (inst>>12) & 0xf;
435
	rm = inst & 0xf;
436
	o1 = reg.r[rn];
437
	if(rn == REGPC)
438
		o1 += 8;
439
	o2 = reg.r[rm];
440
	if(rm == REGPC)
441
		o2 += 8;
442
 
443
	dpex(inst, o1, o2, rd);
444
	if(trace)
445
		itrace("%s%s\tR%d,R%d,R%d =#%x",
446
			reg.ip->name, cond[reg.cond],
447
			rm, rn, rd,
448
			reg.r[rd]);
449
	if(rd == REGPC)
450
		reg.r[rd] -= 4;
451
}
452
 
453
/*
454
 * data processing instruction (R<>#),R,R
455
 */
456
void
457
Idp1(ulong inst)
458
{
459
	int rn, rd, rm, st, sc;
460
	long o1, o2;
461
 
462
	rn = (inst>>16) & 0xf;
463
	rd = (inst>>12) & 0xf;
464
	rm = inst & 0xf;
465
	st = (inst>>5) & 0x3;
466
	sc = (inst>>7) & 0x1f;
467
	o1 = reg.r[rn];
468
	if(rn == REGPC)
469
		o1 += 8;
470
	o2 = reg.r[rm];
471
	if(rm == REGPC)
472
		o2 += 8;
473
	o2 = shift(o2, st, sc, 0);
474
	dpex(inst, o1, o2, rd);
475
	if(trace)
476
		itrace("%s%s\tR%d%s%d,R%d,R%d =#%x",
477
			reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd,
478
			reg.r[rd]);
479
	if(rd == REGPC)
480
		reg.r[rd] -= 4;
481
}
482
 
483
/*
484
 * data processing instruction (R<>R),R,R
485
 */
486
void
487
Idp2(ulong inst)
488
{
489
	int rn, rd, rm, rs, st;
490
	long o1, o2, o3;
491
 
492
	rn = (inst>>16) & 0xf;
493
	rd = (inst>>12) & 0xf;
494
	rm = inst & 0xf;
495
	st = (inst>>5) & 0x3;
496
	rs = (inst>>8) & 0xf;
497
	o1 = reg.r[rn];
498
	if(rn == REGPC)
499
		o1 += 8;
500
	o2 = reg.r[rm];
501
	if(rm == REGPC)
502
		o2 += 8;
503
	o3 = reg.r[rs];
504
	if(rs == REGPC)
505
		o3 += 8;
506
	o2 = shift(o2, st, o3, 1);
507
	dpex(inst, o1, o2, rd);
508
	if(trace)
509
		itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x",
510
			reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd,
511
			reg.r[rd]);
512
	if(rd == REGPC)
513
		reg.r[rd] -= 4;
514
}
515
 
516
/*
517
 * data processing instruction #<>#,R,R
518
 */
519
void
520
Idp3(ulong inst)
521
{
522
	int rn, rd, sc;
523
	long o1, o2;
524
 
525
	rn = (inst>>16) & 0xf;
526
	rd = (inst>>12) & 0xf;
527
	o1 = reg.r[rn];
528
	if(rn == REGPC)
529
		o1 += 8;
530
	o2 = inst & 0xff;
531
	sc = (inst>>7) & 0x1e;
532
	o2 = (o2 >> sc) | (o2 << (32 - sc));
533
 
534
	dpex(inst, o1, o2, rd);
535
	if(trace)
536
		itrace("%s%s\t#%x,R%d,R%d =#%x",
537
			reg.ip->name, cond[reg.cond], o2, rn, rd,
538
			reg.r[rd]);
539
	if(rd == REGPC)
540
		reg.r[rd] -= 4;
541
}
542
 
543
void
544
Imul(ulong inst)
545
{
546
	int rs, rd, rm;
547
 
548
	rd = (inst>>16) & 0xf;
549
	rs = (inst>>8) & 0xf;
550
	rm = inst & 0xf;
551
 
552
	if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm)
553
		undef(inst);
554
 
555
	reg.r[rd] = reg.r[rm]*reg.r[rs];
556
 
557
	if(trace)
558
		itrace("%s%s\tR%d,R%d,R%d =#%x",
559
			reg.ip->name, cond[reg.cond], rs, rm, rd,
560
			reg.r[rd]);
561
}
562
 
563
void
564
Imull(ulong inst)
565
{
566
	vlong v;
567
	int rs, rd, rm, rn;
568
 
569
	rd = (inst>>16) & 0xf;
570
	rn = (inst>>12) & 0xf;
571
	rs = (inst>>8) & 0xf;
572
	rm = inst & 0xf;
573
 
574
	if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC
575
	|| rd == rm || rn == rm || rd == rn)
576
		undef(inst);
577
 
578
	if(inst & (1<<22)){
579
		v = (vlong)reg.r[rm] * (vlong)reg.r[rs];
580
		if(inst & (1 << 21))
581
			v += reg.r[rn];
582
	}else{
583
		v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs];
584
		if(inst & (1 << 21))
585
			v += (ulong)reg.r[rn];
586
	}
587
	reg.r[rd] = v >> 32;
588
	reg.r[rn] = v;
589
 
590
	if(trace)
591
		itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx",
592
			reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
593
			v);
594
}
595
 
596
void
597
Imula(ulong inst)
598
{
599
	int rs, rd, rm, rn;
600
 
601
	rd = (inst>>16) & 0xf;
602
	rn = (inst>>12) & 0xf;
603
	rs = (inst>>8) & 0xf;
604
	rm = inst & 0xf;
605
 
606
	if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm)
607
		undef(inst);
608
 
609
	reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn];
610
 
611
	if(trace)
612
		itrace("%s%s\tR%d,R%d,R%d,R%d =#%x",
613
			reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
614
			reg.r[rd]);
615
}
616
 
617
void
618
Iswap(ulong inst)
619
{
620
	int rn, rd, rm;
621
	ulong address, value, bbit;
622
 
623
	bbit = inst & (1<<22);
624
	rn = (inst>>16) & 0xf;
625
	rd = (inst>>12) & 0xf;
626
	rm = (inst>>0) & 0xf;
627
 
628
	address = reg.r[rn];
629
	if(bbit) {
630
		value = getmem_b(address);
631
		putmem_b(address, reg.r[rm]);
632
	} else {
633
		value = getmem_w(address);
634
		putmem_w(address, reg.r[rm]);
635
	}
636
	reg.r[rd] = value;
637
 
638
	if(trace) {
639
		char *bw, *dotc;
640
 
641
		bw = "";
642
		if(bbit)
643
			bw = "B";
644
		dotc = cond[reg.cond];
645
 
646
		itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x",
647
			bw, dotc,
648
			rn, rd,
649
			address, value);
650
	}
651
}
652
 
653
/*
654
 * load/store word/byte
655
 */
656
void
657
Imem1(ulong inst)
658
{
659
	int rn, rd, off, rm, sc, st;
660
	ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25;
661
 
662
	bit25 = inst & (1<<25);
663
	pbit = inst & (1<<24);
664
	ubit = inst & (1<<23);
665
	bbit = inst & (1<<22);
666
	wbit = inst & (1<<21);
667
	lbit = inst & (1<<20);
668
	rn = (inst>>16) & 0xf;
669
	rd = (inst>>12) & 0xf;
670
 
671
	SET(st);
672
	SET(sc);
673
	SET(rm);
674
	if(bit25) {
675
		rm = inst & 0xf;
676
		st = (inst>>5) & 0x3;
677
		sc = (inst>>7) & 0x1f;
678
		off = reg.r[rm];
679
		if(rm == REGPC)
680
			off += 8;
681
		off = shift(off, st, sc, 0);
682
	} else {
683
		off = inst & 0xfff;
684
	}
685
	if(!ubit)
686
		off = -off;
687
	if(rn == REGPC)
688
		off += 8;
689
 
690
	address = reg.r[rn];
691
	if(pbit)
692
		address += off;
693
 
694
	if(lbit) {
695
		if(bbit)
696
			value = getmem_b(address);
697
		else
698
			value = getmem_w(address);
699
		if(rd == REGPC)
700
			value -= 4;
701
		reg.r[rd] = value;
702
	} else {
703
		value = reg.r[rd];
704
		if(rd == REGPC)
705
			value -= 4;
706
		if(bbit)
707
			putmem_b(address, value);
708
		else
709
			putmem_w(address, value);
710
	}
711
	if(!(pbit && !wbit))
712
		reg.r[rn] += off;
713
 
714
	if(trace) {
715
		char *bw, *dotp, *dotc;
716
 
717
		bw = "W";
718
		if(bbit)
719
			bw = "BU";
720
		dotp = "";
721
		if(!pbit)
722
			dotp = ".P";
723
		dotc = cond[reg.cond];
724
 
725
		if(lbit) {
726
			if(!bit25)
727
				itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
728
					bw, dotp, dotc,
729
					off, rn, rd,
730
					address, value);
731
			else
732
				itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d  #%lux=#%x",
733
					bw, dotp, dotc,
734
					rm, shtype[st], sc, rn, rd,
735
					address, value);
736
		} else {
737
			if(!bit25)
738
				itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
739
					bw, dotp, dotc,
740
					rd, off, rn,
741
					address, value);
742
			else
743
				itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x",
744
					bw, dotp, dotc,
745
					rd, rm, shtype[st], sc, rn,
746
					address, value);
747
		}
748
	}
749
}
750
 
751
/*
752
 * load/store unsigned byte/half word
753
 */
754
void
755
Imem2(ulong inst)
756
{
757
	int rn, rd, off, rm;
758
	ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22;
759
 
760
	pbit = inst & (1<<24);
761
	ubit = inst & (1<<23);
762
	bit22 = inst & (1<<22);
763
	wbit = inst & (1<<21);
764
	lbit = inst & (1<<20);
765
	sbit = inst & (1<<6);
766
	hbit = inst & (1<<5);
767
	rn = (inst>>16) & 0xf;
768
	rd = (inst>>12) & 0xf;
769
 
770
	SET(rm);
771
	if(bit22) {
772
		off = ((inst>>4) & 0xf0) | (inst & 0xf);
773
	} else {
774
		rm = inst & 0xf;
775
		off = reg.r[rm];
776
		if(rm == REGPC)
777
			off += 8;
778
	}
779
	if(!ubit)
780
		off = -off;
781
	if(rn == REGPC)
782
		off += 8;
783
 
784
	address = reg.r[rn];
785
	if(pbit)
786
		address += off;
787
 
788
	if(lbit) {
789
		if(hbit) {
790
			value = getmem_h(address);
791
			if(sbit && (value & 0x8000))
792
				value |= 0xffff0000;
793
		} else {
794
			value = getmem_b(address);
795
			if(value & 0x80)
796
				value |= 0xffffff00;
797
		}
798
		if(rd == REGPC)
799
			value -= 4;
800
		reg.r[rd] = value;
801
	} else {
802
		value = reg.r[rd];
803
		if(rd == REGPC)
804
			value -= 4;
805
		if(hbit) {
806
			putmem_h(address, value);
807
		} else {
808
			putmem_b(address, value);
809
		}
810
	}
811
	if(!(pbit && !wbit))
812
		reg.r[rn] += off;
813
 
814
	if(trace) {
815
		char *hb, *dotp, *dotc;
816
 
817
		hb = "B";
818
		if(hbit)
819
			hb = "H";
820
		dotp = "";
821
		if(!pbit)
822
			dotp = ".P";
823
		dotc = cond[reg.cond];
824
 
825
		if(lbit) {
826
			if(bit22)
827
				itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
828
					hb, dotp, dotc,
829
					off, rn, rd,
830
					address, value);
831
			else
832
				itrace("MOV%s%s%s\t(R%d)(R%d),R%d  #%lux=#%x",
833
					hb, dotp, dotc,
834
					rm, rn, rd,
835
					address, value);
836
		} else {
837
			if(bit22)
838
				itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
839
					hb, dotp, dotc,
840
					rd, off, rn,
841
					address, value);
842
			else
843
				itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x",
844
					hb, dotp, dotc,
845
					rd, rm, rn,
846
					address, value);
847
		}
848
	}
849
}
850
 
851
void
852
Ilsm(ulong inst)
853
{
854
	char pbit, ubit, sbit, wbit, lbit;
855
	int i, rn, reglist;
856
	ulong address, predelta, postdelta;
857
 
858
	pbit = (inst>>24) & 0x1;
859
	ubit = (inst>>23) & 0x1;
860
	sbit = (inst>>22) & 0x1;
861
	wbit = (inst>>21) & 0x1;
862
	lbit = (inst>>20) & 0x1;
863
	rn =   (inst>>16) & 0xf;
864
	reglist = inst & 0xffff;
865
 
866
	if(reglist & 0x8000)
867
		undef(reg.ir);
868
	if(sbit)
869
		undef(reg.ir);
870
 
871
	address = reg.r[rn];
872
 
873
	if(pbit) {
874
		predelta = 4;
875
		postdelta = 0;
876
	} else {
877
		predelta = 0;
878
		postdelta = 4;
879
	}
880
	if(ubit) {
881
		for (i = 0; i < 16; ++i) {
882
			if(!(reglist & (1 << i)))
883
				continue;
884
			address += predelta;
885
			if(lbit)
886
				reg.r[i] = getmem_w(address);
887
			else
888
				putmem_w(address, reg.r[i]);
889
			address += postdelta;
890
		}
891
	} else {
892
		for (i = 15; 0 <= i; --i) {
893
			if(!(reglist & (1 << i)))
894
				continue;
895
			address -= predelta;
896
			if(lbit)
897
				reg.r[i] = getmem_w(address);
898
			else
899
				putmem_w(address, reg.r[i]);
900
			address -= postdelta;
901
		}
902
	}
903
	if(wbit) {
904
		reg.r[rn] = address;
905
	}
906
 
907
	if(trace) {
908
		itrace("%s.%c%c\tR%d=%lux%s, <%lux>",
909
			(lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'),
910
			rn, reg.r[rn], (wbit ? "!" : ""), reglist);
911
	}
912
}
913
 
914
void
915
Ib(ulong inst)
916
{
917
	long v;
918
 
919
	v = inst & 0xffffff;
920
	v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
921
	if(trace)
922
		itrace("B%s\t#%lux", cond[reg.cond], v);
923
	reg.r[REGPC] = v - 4;
924
}
925
 
926
void
927
Ibl(ulong inst)
928
{
929
	long v;
930
	Symbol s;
931
 
932
	v = inst & 0xffffff;
933
	v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
934
	if(trace)
935
		itrace("BL%s\t#%lux", cond[reg.cond], v);
936
 
937
	if(calltree) {
938
		findsym(v, CTEXT, &s);
939
		Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name);
940
		printparams(&s, reg.r[13]);
941
		Bprint(bioout, "from ");
942
		printsource(reg.r[REGPC]);
943
		Bputc(bioout, '\n');
944
	}
945
 
946
	reg.r[REGLINK] = reg.r[REGPC] + 4;
947
	reg.r[REGPC] = v - 4;
948
}