xref: /plan9/sys/src/cmd/5i/run.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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
runcmp(void)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
runteq(void)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
runtst(void)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
run(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
undef(ulong inst)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
shift(long v,int st,int sc,int isreg)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
dpex(long inst,long o1,long o2,int rd)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
Idp0(ulong inst)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
Idp1(ulong inst)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
Idp2(ulong inst)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
Idp3(ulong inst)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
Imul(ulong inst)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
Imull(ulong inst)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
Imula(ulong inst)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
Iswap(ulong inst)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
Imem1(ulong inst)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
Imem2(ulong inst)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
Ilsm(ulong inst)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
Ib(ulong inst)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
Ibl(ulong inst)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 }
949