xref: /plan9-contrib/sys/src/cmd/5i/run.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <mach.h>
57dd7cddfSDavid du Colombier #include "arm.h"
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier static	int	dummy;
87dd7cddfSDavid du Colombier static	char*	shtype[4] =
97dd7cddfSDavid du Colombier {
107dd7cddfSDavid du Colombier 	"<<",
117dd7cddfSDavid du Colombier 	">>",
127dd7cddfSDavid du Colombier 	"->",
137dd7cddfSDavid du Colombier 	"@>",
147dd7cddfSDavid du Colombier };
157dd7cddfSDavid du Colombier static	char*	cond[16] =
167dd7cddfSDavid du Colombier {
177dd7cddfSDavid du Colombier 	".EQ",	".NE",	".HS",	".LO",
187dd7cddfSDavid du Colombier 	".MI",	".PL",	".VS",	".VC",
197dd7cddfSDavid du Colombier 	".HI",	".LS",	".GE",	".LT",
207dd7cddfSDavid du Colombier 	".GT",	".LE",	"",	".NO",
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier void	Idp0(ulong);
247dd7cddfSDavid du Colombier void	Idp1(ulong);
257dd7cddfSDavid du Colombier void	Idp2(ulong);
267dd7cddfSDavid du Colombier void	Idp3(ulong);
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier void	Imul(ulong);
297dd7cddfSDavid du Colombier void	Imula(ulong);
3080ee5cbfSDavid du Colombier void	Imull(ulong);
317dd7cddfSDavid du Colombier 
3259cc4ca5SDavid du Colombier void	Iswap(ulong);
3359cc4ca5SDavid du Colombier void	Imem1(ulong);
3459cc4ca5SDavid du Colombier void	Imem2(ulong);
357dd7cddfSDavid du Colombier void	Ilsm(ulong inst);
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier void	Ib(ulong);
387dd7cddfSDavid du Colombier void	Ibl(ulong);
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier void	Ssyscall(ulong);
417dd7cddfSDavid du Colombier 
4280ee5cbfSDavid du Colombier Inst itab[] =
437dd7cddfSDavid du Colombier {
4480ee5cbfSDavid du Colombier 	{ Idp0,		"AND",	Iarith },	/* 00 - r,r,r */
4580ee5cbfSDavid du Colombier 	{ Idp0,		"EOR",	Iarith },	/* 01 */
4680ee5cbfSDavid du Colombier 	{ Idp0,		"SUB",	Iarith },	/* 02 */
4780ee5cbfSDavid du Colombier 	{ Idp0,		"RSB",	Iarith },	/* 03 */
4880ee5cbfSDavid du Colombier 	{ Idp0,		"ADD",	Iarith },	/* 04 */
4980ee5cbfSDavid du Colombier 	{ Idp0,		"ADC",	Iarith },	/* 05 */
5080ee5cbfSDavid du Colombier 	{ Idp0,		"SBC",	Iarith },	/* 06 */
5180ee5cbfSDavid du Colombier 	{ Idp0,		"RSC",	Iarith },	/* 07 */
5280ee5cbfSDavid du Colombier 	{ Idp0,		"TST",	Iarith },	/* 08 */
5380ee5cbfSDavid du Colombier 	{ Idp0,		"TEQ",	Iarith },	/* 09 */
547dd7cddfSDavid du Colombier 
5580ee5cbfSDavid du Colombier 	{ Idp0,		"CMP",	Iarith },	/* 10 */
5680ee5cbfSDavid du Colombier 	{ Idp0,		"CMN",	Iarith },	/* 11 */
5780ee5cbfSDavid du Colombier 	{ Idp0,		"ORR",	Iarith },	/* 12 */
5880ee5cbfSDavid du Colombier 	{ Idp0,		"MOV",	Iarith },	/* 13 */
5980ee5cbfSDavid du Colombier 	{ Idp0,		"BIC",	Iarith },	/* 14 */
6080ee5cbfSDavid du Colombier 	{ Idp0,		"MVN",	Iarith },	/* 15 */
6180ee5cbfSDavid du Colombier 	{ Idp1,		"AND",	Iarith },	/* 16 */
6280ee5cbfSDavid du Colombier 	{ Idp1,		"EOR",	Iarith },	/* 17 */
6380ee5cbfSDavid du Colombier 	{ Idp1,		"SUB",	Iarith },	/* 18 */
6480ee5cbfSDavid du Colombier 	{ Idp1,		"RSB",	Iarith },	/* 19 */
657dd7cddfSDavid du Colombier 
6680ee5cbfSDavid du Colombier 	{ Idp1,		"ADD",	Iarith },	/* 20 */
6780ee5cbfSDavid du Colombier 	{ Idp1,		"ADC",	Iarith },	/* 21 */
6880ee5cbfSDavid du Colombier 	{ Idp1,		"SBC",	Iarith },	/* 22 */
6980ee5cbfSDavid du Colombier 	{ Idp1,		"RSC",	Iarith },	/* 23 */
7080ee5cbfSDavid du Colombier 	{ Idp1,		"TST",	Iarith },	/* 24 */
7180ee5cbfSDavid du Colombier 	{ Idp1,		"TEQ",	Iarith },	/* 25 */
7280ee5cbfSDavid du Colombier 	{ Idp1,		"CMP",	Iarith },	/* 26 */
7380ee5cbfSDavid du Colombier 	{ Idp1,		"CMN",	Iarith },	/* 27 */
7480ee5cbfSDavid du Colombier 	{ Idp1,		"ORR",	Iarith },	/* 28 */
7580ee5cbfSDavid du Colombier 	{ Idp1,		"MOV",	Iarith },	/* 29 */
767dd7cddfSDavid du Colombier 
7780ee5cbfSDavid du Colombier 	{ Idp1,		"BIC",	Iarith },	/* 30 */
7880ee5cbfSDavid du Colombier 	{ Idp1,		"MVN",	Iarith },	/* 31 */
7980ee5cbfSDavid du Colombier 	{ Idp2,		"AND",	Iarith },	/* 32 */
8080ee5cbfSDavid du Colombier 	{ Idp2,		"EOR",	Iarith },	/* 33 */
8180ee5cbfSDavid du Colombier 	{ Idp2,		"SUB",	Iarith },	/* 34 */
8280ee5cbfSDavid du Colombier 	{ Idp2,		"RSB",	Iarith },	/* 35 */
8380ee5cbfSDavid du Colombier 	{ Idp2,		"ADD",	Iarith },	/* 36 */
8480ee5cbfSDavid du Colombier 	{ Idp2,		"ADC",	Iarith },	/* 37 */
8580ee5cbfSDavid du Colombier 	{ Idp2,		"SBC",	Iarith },	/* 38 */
8680ee5cbfSDavid du Colombier 	{ Idp2,		"RSC",	Iarith },	/* 39 */
877dd7cddfSDavid du Colombier 
8880ee5cbfSDavid du Colombier 	{ Idp2,		"TST",	Iarith },	/* 40 */
8980ee5cbfSDavid du Colombier 	{ Idp2,		"TEQ",	Iarith },	/* 41 */
9080ee5cbfSDavid du Colombier 	{ Idp2,		"CMP",	Iarith },	/* 42 */
9180ee5cbfSDavid du Colombier 	{ Idp2,		"CMN",	Iarith },	/* 43 */
9280ee5cbfSDavid du Colombier 	{ Idp2,		"ORR",	Iarith },	/* 44 */
9380ee5cbfSDavid du Colombier 	{ Idp2,		"MOV",	Iarith },	/* 45 */
9480ee5cbfSDavid du Colombier 	{ Idp2,		"BIC",	Iarith },	/* 46 */
9580ee5cbfSDavid du Colombier 	{ Idp2,		"MVN",	Iarith },	/* 47 */
9680ee5cbfSDavid du Colombier 	{ Idp3,		"AND",	Iarith },	/* 48 - i,r,r */
9780ee5cbfSDavid du Colombier 	{ Idp3,		"EOR",	Iarith },	/* 49 */
987dd7cddfSDavid du Colombier 
9980ee5cbfSDavid du Colombier 	{ Idp3,		"SUB",	Iarith },	/* 50 */
10080ee5cbfSDavid du Colombier 	{ Idp3,		"RSB",	Iarith },	/* 51 */
10180ee5cbfSDavid du Colombier 	{ Idp3,		"ADD",	Iarith },	/* 52 */
10280ee5cbfSDavid du Colombier 	{ Idp3,		"ADC",	Iarith },	/* 53 */
10380ee5cbfSDavid du Colombier 	{ Idp3,		"SBC",	Iarith },	/* 54 */
10480ee5cbfSDavid du Colombier 	{ Idp3,		"RSC",	Iarith },	/* 55 */
10580ee5cbfSDavid du Colombier 	{ Idp3,		"TST",	Iarith },	/* 56 */
10680ee5cbfSDavid du Colombier 	{ Idp3,		"TEQ",	Iarith },	/* 57 */
10780ee5cbfSDavid du Colombier 	{ Idp3,		"CMP",	Iarith },	/* 58 */
10880ee5cbfSDavid du Colombier 	{ Idp3,		"CMN",	Iarith },	/* 59 */
1097dd7cddfSDavid du Colombier 
11080ee5cbfSDavid du Colombier 	{ Idp3,		"ORR",	Iarith },	/* 60 */
11180ee5cbfSDavid du Colombier 	{ Idp3,		"MOV",	Iarith },	/* 61 */
11280ee5cbfSDavid du Colombier 	{ Idp3,		"BIC",	Iarith },	/* 62 */
11380ee5cbfSDavid du Colombier 	{ Idp3,		"MVN",	Iarith },	/* 63 */
11480ee5cbfSDavid du Colombier 	{ Imul,		"MUL",	Iarith },	/* 64 */
11580ee5cbfSDavid du Colombier 	{ Imula,	"MULA",	Iarith },	/* 65 */
1167dd7cddfSDavid du Colombier 
11780ee5cbfSDavid du Colombier 	{ Iswap,	"SWPW",	Imem },	/* 66 */
11880ee5cbfSDavid du Colombier 	{ Iswap,	"SWPBU",	Imem },	/* 67 */
1197dd7cddfSDavid du Colombier 
12080ee5cbfSDavid du Colombier 	{ Imem2,	"MOV",	Imem },	/* 68 load/store h/sb */
12180ee5cbfSDavid du Colombier 	{ Imem2,	"MOV",	Imem },	/* 69 */
12280ee5cbfSDavid du Colombier 	{ Imem2,	"MOV",	Imem },	/* 70 */
12380ee5cbfSDavid du Colombier 	{ Imem2,	"MOV",	Imem },	/* 71 */
12459cc4ca5SDavid du Colombier 
12580ee5cbfSDavid du Colombier 	{ Imem1,	"MOVW",	Imem },	/* 72 load/store w/ub i,r */
12680ee5cbfSDavid du Colombier 	{ Imem1,	"MOVB",	Imem },	/* 73 */
12780ee5cbfSDavid du Colombier 	{ Imem1,	"MOVW",	Imem },	/* 74 */
12880ee5cbfSDavid du Colombier 	{ Imem1,	"MOVB",	Imem },	/* 75 */
12980ee5cbfSDavid du Colombier 	{ Imem1,	"MOVW",	Imem },	/* 76 load/store r,r */
13080ee5cbfSDavid du Colombier 	{ Imem1,	"MOVB",	Imem },	/* 77 */
13180ee5cbfSDavid du Colombier 	{ Imem1,	"MOVW",	Imem },	/* 78 */
13280ee5cbfSDavid du Colombier 	{ Imem1,	"MOVB",	Imem },	/* 79 */
13359cc4ca5SDavid du Colombier 
13480ee5cbfSDavid du Colombier 	{ Ilsm,		"LDM",	Imem },	/* 80 block move r,r */
13580ee5cbfSDavid du Colombier 	{ Ilsm,		"STM",	Imem },	/* 81 */
13680ee5cbfSDavid du Colombier 	{ Ib,		"B",	Ibranch },		/* 82 branch */
13780ee5cbfSDavid du Colombier 	{ Ibl,		"BL",	Ibranch },		/* 83 */
13880ee5cbfSDavid du Colombier 	{ Ssyscall,	"SWI",	Isyscall },	/* 84 co processor */
13980ee5cbfSDavid du Colombier 	{ undef,	"undef" },	/* 85 */
14080ee5cbfSDavid du Colombier 	{ undef,	"undef" },	/* 86 */
14180ee5cbfSDavid du Colombier 	{ undef,	"undef"  },	/* 87 */
14280ee5cbfSDavid du Colombier 	{ Imull,	"MULLU",	Iarith },	/* 88 */
14380ee5cbfSDavid du Colombier 	{ Imull,	"MULALU",	Iarith },	/* 89 */
14480ee5cbfSDavid du Colombier 	{ Imull,	"MULL",	Iarith  },	/* 90 */
14580ee5cbfSDavid du Colombier 	{ Imull,	"MULAL",	Iarith  },	/* 91 */
14680ee5cbfSDavid du Colombier 	{ undef,	"undef"  },	/* 92 */
14780ee5cbfSDavid du Colombier 
14880ee5cbfSDavid du Colombier 	{ 0 }
1497dd7cddfSDavid du Colombier };
1507dd7cddfSDavid du Colombier 
1517dd7cddfSDavid du Colombier int
runcmp(void)1527dd7cddfSDavid du Colombier runcmp(void)
1537dd7cddfSDavid du Colombier {
1547dd7cddfSDavid du Colombier 	switch(reg.cond) {
1557dd7cddfSDavid du Colombier 	case 0x0:	/* eq */	return (reg.cc1 == reg.cc2);
1567dd7cddfSDavid du Colombier 	case 0x1:	/* ne */	return (reg.cc1 != reg.cc2);
1577dd7cddfSDavid du Colombier 	case 0x2:	/* hs */	return ((ulong)reg.cc1 >= (ulong)reg.cc2);
1587dd7cddfSDavid du Colombier 	case 0x3:	/* lo */	return ((ulong)reg.cc1 < (ulong)reg.cc2);
15980ee5cbfSDavid du Colombier 	case 0x4:	/* mi */	return (reg.cc1 - reg.cc2 < 0);
16080ee5cbfSDavid du Colombier 	case 0x5:	/* pl */	return (reg.cc1 - reg.cc2 >= 0);
1617dd7cddfSDavid du Colombier 	case 0x8:	/* hi */	return ((ulong)reg.cc1 > (ulong)reg.cc2);
1627dd7cddfSDavid du Colombier 	case 0x9:	/* ls */	return ((ulong)reg.cc1 <= (ulong)reg.cc2);
1637dd7cddfSDavid du Colombier 	case 0xa:	/* ge */	return (reg.cc1 >= reg.cc2);
1647dd7cddfSDavid du Colombier 	case 0xb:	/* lt */	return (reg.cc1 < reg.cc2);
1657dd7cddfSDavid du Colombier 	case 0xc:	/* gt */	return (reg.cc1 > reg.cc2);
1667dd7cddfSDavid du Colombier 	case 0xd:	/* le */	return (reg.cc1 <= reg.cc2);
1677dd7cddfSDavid du Colombier 	case 0xe:	/* al */	return 1;
1687dd7cddfSDavid du Colombier 	case 0xf:	/* nv */	return 0;
1697dd7cddfSDavid du Colombier 	default:
1707dd7cddfSDavid du Colombier 		Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
1717dd7cddfSDavid du Colombier 			reg.cond, reg.cc1, reg.cc2);
1727dd7cddfSDavid du Colombier 		undef(reg.ir);
1737dd7cddfSDavid du Colombier 		return 0;
1747dd7cddfSDavid du Colombier 	}
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier int
runteq(void)178*9a747e4fSDavid du Colombier runteq(void)
179*9a747e4fSDavid du Colombier {
180*9a747e4fSDavid du Colombier 	long res = reg.cc1 ^ reg.cc2;
181*9a747e4fSDavid du Colombier 	switch(reg.cond) {
182*9a747e4fSDavid du Colombier 	case 0x0:	/* eq */	return res == 0;
183*9a747e4fSDavid du Colombier 	case 0x1:	/* ne */	return res != 0;
184*9a747e4fSDavid du Colombier 	case 0x4:	/* mi */	return (res & SIGNBIT) != 0;
185*9a747e4fSDavid du Colombier 	case 0x5:	/* pl */	return (res & SIGNBIT) == 0;
186*9a747e4fSDavid du Colombier 	case 0xe:	/* al */	return 1;
187*9a747e4fSDavid du Colombier 	case 0xf:	/* nv */	return 0;
188*9a747e4fSDavid du Colombier 	default:
189*9a747e4fSDavid du Colombier 		Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
190*9a747e4fSDavid du Colombier 			reg.cond, reg.cc1, reg.cc2);
191*9a747e4fSDavid du Colombier 		undef(reg.ir);
192*9a747e4fSDavid du Colombier 		return 0;
193*9a747e4fSDavid du Colombier 	}
194*9a747e4fSDavid du Colombier }
195*9a747e4fSDavid du Colombier 
196*9a747e4fSDavid du Colombier int
runtst(void)1977dd7cddfSDavid du Colombier runtst(void)
1987dd7cddfSDavid du Colombier {
1997dd7cddfSDavid du Colombier 	long res = reg.cc1 & reg.cc2;
2007dd7cddfSDavid du Colombier 	switch(reg.cond) {
2017dd7cddfSDavid du Colombier 	case 0x0:	/* eq */	return res == 0;
2027dd7cddfSDavid du Colombier 	case 0x1:	/* ne */	return res != 0;
2037dd7cddfSDavid du Colombier 	case 0x4:	/* mi */	return (res & SIGNBIT) != 0;
2047dd7cddfSDavid du Colombier 	case 0x5:	/* pl */	return (res & SIGNBIT) == 0;
2057dd7cddfSDavid du Colombier 	case 0xe:	/* al */	return 1;
2067dd7cddfSDavid du Colombier 	case 0xf:	/* nv */	return 0;
2077dd7cddfSDavid du Colombier 	default:
2087dd7cddfSDavid du Colombier 		Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
2097dd7cddfSDavid du Colombier 			reg.cond, reg.cc1, reg.cc2);
2107dd7cddfSDavid du Colombier 		undef(reg.ir);
2117dd7cddfSDavid du Colombier 		return 0;
2127dd7cddfSDavid du Colombier 	}
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier void
run(void)2167dd7cddfSDavid du Colombier run(void)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier 	int execute;
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier 	do {
2217dd7cddfSDavid du Colombier 		if(trace)
2227dd7cddfSDavid du Colombier 			Bflush(bioout);
2237dd7cddfSDavid du Colombier 		reg.ar = reg.r[REGPC];
2247dd7cddfSDavid du Colombier 		reg.ir = ifetch(reg.ar);
22559cc4ca5SDavid du Colombier 		reg.class = armclass(reg.ir);
22659cc4ca5SDavid du Colombier 		reg.ip = &itab[reg.class];
2277dd7cddfSDavid du Colombier 		reg.cond = (reg.ir>>28) & 0xf;
2287dd7cddfSDavid du Colombier 		switch(reg.compare_op) {
2297dd7cddfSDavid du Colombier 		case CCcmp:
2307dd7cddfSDavid du Colombier 			execute = runcmp();
2317dd7cddfSDavid du Colombier 			break;
232*9a747e4fSDavid du Colombier 		case CCteq:
233*9a747e4fSDavid du Colombier 			execute = runteq();
234*9a747e4fSDavid du Colombier 			break;
2357dd7cddfSDavid du Colombier 		case CCtst:
2367dd7cddfSDavid du Colombier 			execute = runtst();
2377dd7cddfSDavid du Colombier 			break;
2387dd7cddfSDavid du Colombier 		default:
2397dd7cddfSDavid du Colombier 			Bprint(bioout, "unimplemented compare operation %x\n",
2407dd7cddfSDavid du Colombier 				reg.compare_op);
24159cc4ca5SDavid du Colombier 			return;
2427dd7cddfSDavid du Colombier 		}
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier 		if(execute) {
2457dd7cddfSDavid du Colombier 			reg.ip->count++;
2467dd7cddfSDavid du Colombier 			(*reg.ip->func)(reg.ir);
2477dd7cddfSDavid du Colombier 		} else {
2487dd7cddfSDavid du Colombier 			if(trace)
2497dd7cddfSDavid du Colombier 				itrace("%s%s	IGNORED",
2507dd7cddfSDavid du Colombier 					reg.ip->name, cond[reg.cond]);
2517dd7cddfSDavid du Colombier 		}
2527dd7cddfSDavid du Colombier 		reg.r[REGPC] += 4;
2537dd7cddfSDavid du Colombier 		if(bplist)
2547dd7cddfSDavid du Colombier 			brkchk(reg.r[REGPC], Instruction);
2557dd7cddfSDavid du Colombier 	} while(--count);
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier void
undef(ulong inst)2597dd7cddfSDavid du Colombier undef(ulong inst)
2607dd7cddfSDavid du Colombier {
26159cc4ca5SDavid du Colombier 	Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n",
26259cc4ca5SDavid du Colombier 		reg.r[REGPC], inst, reg.class);
2637dd7cddfSDavid du Colombier 	longjmp(errjmp, 0);
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier 
266*9a747e4fSDavid du Colombier long
shift(long v,int st,int sc,int isreg)267*9a747e4fSDavid du Colombier shift(long v, int st, int sc, int isreg)
268*9a747e4fSDavid du Colombier {
269*9a747e4fSDavid du Colombier 	if(sc == 0) {
270*9a747e4fSDavid du Colombier 		switch(st) {
271*9a747e4fSDavid du Colombier 		case 0:	/* logical left */
272*9a747e4fSDavid du Colombier 			reg.cout = reg.cbit;
273*9a747e4fSDavid du Colombier 			break;
274*9a747e4fSDavid du Colombier 		case 1:	/* logical right */
275*9a747e4fSDavid du Colombier 			reg.cout = (v >> 31) & 1;
276*9a747e4fSDavid du Colombier 			break;
277*9a747e4fSDavid du Colombier 		case 2:	/* arith right */
278*9a747e4fSDavid du Colombier 			reg.cout = reg.cbit;
279*9a747e4fSDavid du Colombier 			break;
280*9a747e4fSDavid du Colombier 		case 3:	/* rotate right */
281*9a747e4fSDavid du Colombier 			if(isreg) {
282*9a747e4fSDavid du Colombier 				reg.cout = reg.cbit;
283*9a747e4fSDavid du Colombier 			}
284*9a747e4fSDavid du Colombier 			else {
285*9a747e4fSDavid du Colombier 				reg.cout = v & 1;
286*9a747e4fSDavid du Colombier 				v = ((ulong)v >> 1) | (reg.cbit << 31);
287*9a747e4fSDavid du Colombier 			}
288*9a747e4fSDavid du Colombier 		}
289*9a747e4fSDavid du Colombier 	}
290*9a747e4fSDavid du Colombier 	else {
291*9a747e4fSDavid du Colombier 		switch(st) {
292*9a747e4fSDavid du Colombier 		case 0:	/* logical left */
293*9a747e4fSDavid du Colombier 			reg.cout = (v >> (32 - sc)) & 1;
294*9a747e4fSDavid du Colombier 			v = v << sc;
295*9a747e4fSDavid du Colombier 			break;
296*9a747e4fSDavid du Colombier 		case 1:	/* logical right */
297*9a747e4fSDavid du Colombier 			reg.cout = (v >> (sc - 1)) & 1;
298*9a747e4fSDavid du Colombier 			v = (ulong)v >> sc;
299*9a747e4fSDavid du Colombier 			break;
300*9a747e4fSDavid du Colombier 		case 2:	/* arith right */
301*9a747e4fSDavid du Colombier 			if(sc >= 32) {
302*9a747e4fSDavid du Colombier 				reg.cout = (v >> 31) & 1;
303*9a747e4fSDavid du Colombier 				if(reg.cout)
304*9a747e4fSDavid du Colombier 					v = 0xFFFFFFFF;
305*9a747e4fSDavid du Colombier 				else
306*9a747e4fSDavid du Colombier 					v = 0;
307*9a747e4fSDavid du Colombier 			}
308*9a747e4fSDavid du Colombier 			else {
309*9a747e4fSDavid du Colombier 				reg.cout = (v >> (sc - 1)) & 1;
310*9a747e4fSDavid du Colombier 				v = (long)v >> sc;
311*9a747e4fSDavid du Colombier 			}
312*9a747e4fSDavid du Colombier 			break;
313*9a747e4fSDavid du Colombier 		case 3:	/* rotate right */
314*9a747e4fSDavid du Colombier 			reg.cout = (v >> (sc - 1)) & 1;
315*9a747e4fSDavid du Colombier 			v = (v << (32-sc)) | ((ulong)v >> sc);
316*9a747e4fSDavid du Colombier 			break;
317*9a747e4fSDavid du Colombier 		}
318*9a747e4fSDavid du Colombier 	}
319*9a747e4fSDavid du Colombier 	return v;
320*9a747e4fSDavid du Colombier }
321*9a747e4fSDavid du Colombier 
3227dd7cddfSDavid du Colombier void
dpex(long inst,long o1,long o2,int rd)3237dd7cddfSDavid du Colombier dpex(long inst, long o1, long o2, int rd)
3247dd7cddfSDavid du Colombier {
325*9a747e4fSDavid du Colombier 	int cbit;
3267dd7cddfSDavid du Colombier 
327*9a747e4fSDavid du Colombier 	cbit = 0;
3287dd7cddfSDavid du Colombier 	switch((inst>>21) & 0xf) {
3297dd7cddfSDavid du Colombier 	case  0:	/* and */
3307dd7cddfSDavid du Colombier 		reg.r[rd] = o1 & o2;
331*9a747e4fSDavid du Colombier 		cbit = 1;
3327dd7cddfSDavid du Colombier 		break;
3337dd7cddfSDavid du Colombier 	case  1:	/* eor */
3347dd7cddfSDavid du Colombier 		reg.r[rd] = o1 ^ o2;
335*9a747e4fSDavid du Colombier 		cbit = 1;
3367dd7cddfSDavid du Colombier 		break;
3377dd7cddfSDavid du Colombier 	case  2:	/* sub */
3387dd7cddfSDavid du Colombier 		reg.r[rd] = o1 - o2;
3397dd7cddfSDavid du Colombier 	case 10:	/* cmp */
3407dd7cddfSDavid du Colombier 		if(inst & Sbit) {
3417dd7cddfSDavid du Colombier 			reg.cc1 = o1;
3427dd7cddfSDavid du Colombier 			reg.cc2 = o2;
3437dd7cddfSDavid du Colombier 			reg.compare_op = CCcmp;
3447dd7cddfSDavid du Colombier 		}
3457dd7cddfSDavid du Colombier 		return;
3467dd7cddfSDavid du Colombier 	case  3:	/* rsb */
3477dd7cddfSDavid du Colombier 		reg.r[rd] = o2 - o1;
3487dd7cddfSDavid du Colombier 		if(inst & Sbit) {
3497dd7cddfSDavid du Colombier 			reg.cc1 = o2;
3507dd7cddfSDavid du Colombier 			reg.cc2 = o1;
3517dd7cddfSDavid du Colombier 			reg.compare_op = CCcmp;
3527dd7cddfSDavid du Colombier 		}
3537dd7cddfSDavid du Colombier 		return;
3547dd7cddfSDavid du Colombier 	case  4:	/* add */
35580ee5cbfSDavid du Colombier 		if(calltree && rd == REGPC && o2 == 0) {
35680ee5cbfSDavid du Colombier 			Symbol s;
35780ee5cbfSDavid du Colombier 
35880ee5cbfSDavid du Colombier 			findsym(o1 + o2, CTEXT, &s);
35980ee5cbfSDavid du Colombier 			Bprint(bioout, "%8lux return to %lux %s r0=%lux\n",
36080ee5cbfSDavid du Colombier 						reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]);
36180ee5cbfSDavid du Colombier 		}
3627dd7cddfSDavid du Colombier 		reg.r[rd] = o1 + o2;
3637dd7cddfSDavid du Colombier 		if(inst & Sbit) {
364*9a747e4fSDavid du Colombier 			if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32))
365*9a747e4fSDavid du Colombier 				reg.cbit = 1;
366*9a747e4fSDavid du Colombier 			else
367*9a747e4fSDavid du Colombier 				reg.cbit = 0;
368*9a747e4fSDavid du Colombier 			reg.cc1 = o2;
369*9a747e4fSDavid du Colombier 			reg.cc2 = -o1;
3707dd7cddfSDavid du Colombier 			reg.compare_op = CCcmp;
3717dd7cddfSDavid du Colombier 		}
3727dd7cddfSDavid du Colombier 		return;
3737dd7cddfSDavid du Colombier 	case  5:	/* adc */
3747dd7cddfSDavid du Colombier 	case  6:	/* sbc */
3757dd7cddfSDavid du Colombier 	case  7:	/* rsc */
3767dd7cddfSDavid du Colombier 		undef(inst);
3777dd7cddfSDavid du Colombier 	case  8:	/* tst */
3787dd7cddfSDavid du Colombier 		if(inst & Sbit) {
3797dd7cddfSDavid du Colombier 			reg.cc1 = o1;
3807dd7cddfSDavid du Colombier 			reg.cc2 = o2;
3817dd7cddfSDavid du Colombier 			reg.compare_op = CCtst;
3827dd7cddfSDavid du Colombier 		}
3837dd7cddfSDavid du Colombier 		return;
3847dd7cddfSDavid du Colombier 	case  9:	/* teq */
3857dd7cddfSDavid du Colombier 		if(inst & Sbit) {
3867dd7cddfSDavid du Colombier 			reg.cc1 = o1;
3877dd7cddfSDavid du Colombier 			reg.cc2 = o2;
3887dd7cddfSDavid du Colombier 			reg.compare_op = CCteq;
3897dd7cddfSDavid du Colombier 		}
3907dd7cddfSDavid du Colombier 		return;
3917dd7cddfSDavid du Colombier 	case 11:	/* cmn */
3927dd7cddfSDavid du Colombier 		if(inst & Sbit) {
3937dd7cddfSDavid du Colombier 			reg.cc1 = o1;
39459cc4ca5SDavid du Colombier 			reg.cc2 = -o2;
39559cc4ca5SDavid du Colombier 			reg.compare_op = CCcmp;
3967dd7cddfSDavid du Colombier 		}
3977dd7cddfSDavid du Colombier 		return;
3987dd7cddfSDavid du Colombier 	case 12:	/* orr */
3997dd7cddfSDavid du Colombier 		reg.r[rd] = o1 | o2;
400*9a747e4fSDavid du Colombier 		cbit = 1;
4017dd7cddfSDavid du Colombier 		break;
4027dd7cddfSDavid du Colombier 	case 13:	/* mov */
4037dd7cddfSDavid du Colombier 		reg.r[rd] = o2;
404*9a747e4fSDavid du Colombier 		cbit = 1;
4057dd7cddfSDavid du Colombier 		break;
4067dd7cddfSDavid du Colombier 	case 14:	/* bic */
4077dd7cddfSDavid du Colombier 		reg.r[rd] = o1 & ~o2;
408*9a747e4fSDavid du Colombier 		cbit = 1;
4097dd7cddfSDavid du Colombier 		break;
4107dd7cddfSDavid du Colombier 	case 15:	/* mvn */
4117dd7cddfSDavid du Colombier 		reg.r[rd] = ~o2;
412*9a747e4fSDavid du Colombier 		cbit = 1;
4137dd7cddfSDavid du Colombier 		break;
4147dd7cddfSDavid du Colombier 	}
4157dd7cddfSDavid du Colombier 	if(inst & Sbit) {
416*9a747e4fSDavid du Colombier 		if(cbit)
417*9a747e4fSDavid du Colombier 			reg.cbit = reg.cout;
4187dd7cddfSDavid du Colombier 		reg.cc1 = reg.r[rd];
4197dd7cddfSDavid du Colombier 		reg.cc2 = 0;
4207dd7cddfSDavid du Colombier 		reg.compare_op = CCcmp;
4217dd7cddfSDavid du Colombier 	}
4227dd7cddfSDavid du Colombier }
4237dd7cddfSDavid du Colombier 
4247dd7cddfSDavid du Colombier /*
4257dd7cddfSDavid du Colombier  * data processing instruction R,R,R
4267dd7cddfSDavid du Colombier  */
4277dd7cddfSDavid du Colombier void
Idp0(ulong inst)4287dd7cddfSDavid du Colombier Idp0(ulong inst)
4297dd7cddfSDavid du Colombier {
4307dd7cddfSDavid du Colombier 	int rn, rd, rm;
4317dd7cddfSDavid du Colombier 	long o1, o2;
4327dd7cddfSDavid du Colombier 
4337dd7cddfSDavid du Colombier 	rn = (inst>>16) & 0xf;
4347dd7cddfSDavid du Colombier 	rd = (inst>>12) & 0xf;
4357dd7cddfSDavid du Colombier 	rm = inst & 0xf;
4367dd7cddfSDavid du Colombier 	o1 = reg.r[rn];
4377dd7cddfSDavid du Colombier 	if(rn == REGPC)
4387dd7cddfSDavid du Colombier 		o1 += 8;
4397dd7cddfSDavid du Colombier 	o2 = reg.r[rm];
4407dd7cddfSDavid du Colombier 	if(rm == REGPC)
4417dd7cddfSDavid du Colombier 		o2 += 8;
4427dd7cddfSDavid du Colombier 
4437dd7cddfSDavid du Colombier 	dpex(inst, o1, o2, rd);
4447dd7cddfSDavid du Colombier 	if(trace)
4457dd7cddfSDavid du Colombier 		itrace("%s%s\tR%d,R%d,R%d =#%x",
4467dd7cddfSDavid du Colombier 			reg.ip->name, cond[reg.cond],
4477dd7cddfSDavid du Colombier 			rm, rn, rd,
4487dd7cddfSDavid du Colombier 			reg.r[rd]);
4497dd7cddfSDavid du Colombier 	if(rd == REGPC)
4507dd7cddfSDavid du Colombier 		reg.r[rd] -= 4;
4517dd7cddfSDavid du Colombier }
4527dd7cddfSDavid du Colombier 
4537dd7cddfSDavid du Colombier /*
4547dd7cddfSDavid du Colombier  * data processing instruction (R<>#),R,R
4557dd7cddfSDavid du Colombier  */
4567dd7cddfSDavid du Colombier void
Idp1(ulong inst)4577dd7cddfSDavid du Colombier Idp1(ulong inst)
4587dd7cddfSDavid du Colombier {
4597dd7cddfSDavid du Colombier 	int rn, rd, rm, st, sc;
4607dd7cddfSDavid du Colombier 	long o1, o2;
4617dd7cddfSDavid du Colombier 
4627dd7cddfSDavid du Colombier 	rn = (inst>>16) & 0xf;
4637dd7cddfSDavid du Colombier 	rd = (inst>>12) & 0xf;
4647dd7cddfSDavid du Colombier 	rm = inst & 0xf;
4657dd7cddfSDavid du Colombier 	st = (inst>>5) & 0x3;
4667dd7cddfSDavid du Colombier 	sc = (inst>>7) & 0x1f;
4677dd7cddfSDavid du Colombier 	o1 = reg.r[rn];
4687dd7cddfSDavid du Colombier 	if(rn == REGPC)
4697dd7cddfSDavid du Colombier 		o1 += 8;
4707dd7cddfSDavid du Colombier 	o2 = reg.r[rm];
4717dd7cddfSDavid du Colombier 	if(rm == REGPC)
4727dd7cddfSDavid du Colombier 		o2 += 8;
473*9a747e4fSDavid du Colombier 	o2 = shift(o2, st, sc, 0);
4747dd7cddfSDavid du Colombier 	dpex(inst, o1, o2, rd);
4757dd7cddfSDavid du Colombier 	if(trace)
4767dd7cddfSDavid du Colombier 		itrace("%s%s\tR%d%s%d,R%d,R%d =#%x",
4777dd7cddfSDavid du Colombier 			reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd,
4787dd7cddfSDavid du Colombier 			reg.r[rd]);
4797dd7cddfSDavid du Colombier 	if(rd == REGPC)
4807dd7cddfSDavid du Colombier 		reg.r[rd] -= 4;
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier 
4837dd7cddfSDavid du Colombier /*
4847dd7cddfSDavid du Colombier  * data processing instruction (R<>R),R,R
4857dd7cddfSDavid du Colombier  */
4867dd7cddfSDavid du Colombier void
Idp2(ulong inst)4877dd7cddfSDavid du Colombier Idp2(ulong inst)
4887dd7cddfSDavid du Colombier {
4897dd7cddfSDavid du Colombier 	int rn, rd, rm, rs, st;
4907dd7cddfSDavid du Colombier 	long o1, o2, o3;
4917dd7cddfSDavid du Colombier 
4927dd7cddfSDavid du Colombier 	rn = (inst>>16) & 0xf;
4937dd7cddfSDavid du Colombier 	rd = (inst>>12) & 0xf;
4947dd7cddfSDavid du Colombier 	rm = inst & 0xf;
4957dd7cddfSDavid du Colombier 	st = (inst>>5) & 0x3;
4967dd7cddfSDavid du Colombier 	rs = (inst>>8) & 0xf;
4977dd7cddfSDavid du Colombier 	o1 = reg.r[rn];
4987dd7cddfSDavid du Colombier 	if(rn == REGPC)
4997dd7cddfSDavid du Colombier 		o1 += 8;
5007dd7cddfSDavid du Colombier 	o2 = reg.r[rm];
5017dd7cddfSDavid du Colombier 	if(rm == REGPC)
5027dd7cddfSDavid du Colombier 		o2 += 8;
5037dd7cddfSDavid du Colombier 	o3 = reg.r[rs];
5047dd7cddfSDavid du Colombier 	if(rs == REGPC)
5057dd7cddfSDavid du Colombier 		o3 += 8;
506*9a747e4fSDavid du Colombier 	o2 = shift(o2, st, o3, 1);
5077dd7cddfSDavid du Colombier 	dpex(inst, o1, o2, rd);
5087dd7cddfSDavid du Colombier 	if(trace)
5097dd7cddfSDavid du Colombier 		itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x",
5107dd7cddfSDavid du Colombier 			reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd,
5117dd7cddfSDavid du Colombier 			reg.r[rd]);
5127dd7cddfSDavid du Colombier 	if(rd == REGPC)
5137dd7cddfSDavid du Colombier 		reg.r[rd] -= 4;
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier 
5167dd7cddfSDavid du Colombier /*
5177dd7cddfSDavid du Colombier  * data processing instruction #<>#,R,R
5187dd7cddfSDavid du Colombier  */
5197dd7cddfSDavid du Colombier void
Idp3(ulong inst)5207dd7cddfSDavid du Colombier Idp3(ulong inst)
5217dd7cddfSDavid du Colombier {
5227dd7cddfSDavid du Colombier 	int rn, rd, sc;
5237dd7cddfSDavid du Colombier 	long o1, o2;
5247dd7cddfSDavid du Colombier 
5257dd7cddfSDavid du Colombier 	rn = (inst>>16) & 0xf;
5267dd7cddfSDavid du Colombier 	rd = (inst>>12) & 0xf;
5277dd7cddfSDavid du Colombier 	o1 = reg.r[rn];
5287dd7cddfSDavid du Colombier 	if(rn == REGPC)
5297dd7cddfSDavid du Colombier 		o1 += 8;
5307dd7cddfSDavid du Colombier 	o2 = inst & 0xff;
5317dd7cddfSDavid du Colombier 	sc = (inst>>7) & 0x1e;
5327dd7cddfSDavid du Colombier 	o2 = (o2 >> sc) | (o2 << (32 - sc));
5337dd7cddfSDavid du Colombier 
5347dd7cddfSDavid du Colombier 	dpex(inst, o1, o2, rd);
5357dd7cddfSDavid du Colombier 	if(trace)
5367dd7cddfSDavid du Colombier 		itrace("%s%s\t#%x,R%d,R%d =#%x",
5377dd7cddfSDavid du Colombier 			reg.ip->name, cond[reg.cond], o2, rn, rd,
5387dd7cddfSDavid du Colombier 			reg.r[rd]);
5397dd7cddfSDavid du Colombier 	if(rd == REGPC)
5407dd7cddfSDavid du Colombier 		reg.r[rd] -= 4;
5417dd7cddfSDavid du Colombier }
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier void
Imul(ulong inst)5447dd7cddfSDavid du Colombier Imul(ulong inst)
5457dd7cddfSDavid du Colombier {
5467dd7cddfSDavid du Colombier 	int rs, rd, rm;
5477dd7cddfSDavid du Colombier 
5487dd7cddfSDavid du Colombier 	rd = (inst>>16) & 0xf;
5497dd7cddfSDavid du Colombier 	rs = (inst>>8) & 0xf;
5507dd7cddfSDavid du Colombier 	rm = inst & 0xf;
5517dd7cddfSDavid du Colombier 
5527dd7cddfSDavid du Colombier 	if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm)
5537dd7cddfSDavid du Colombier 		undef(inst);
5547dd7cddfSDavid du Colombier 
5557dd7cddfSDavid du Colombier 	reg.r[rd] = reg.r[rm]*reg.r[rs];
5567dd7cddfSDavid du Colombier 
5577dd7cddfSDavid du Colombier 	if(trace)
5587dd7cddfSDavid du Colombier 		itrace("%s%s\tR%d,R%d,R%d =#%x",
5597dd7cddfSDavid du Colombier 			reg.ip->name, cond[reg.cond], rs, rm, rd,
5607dd7cddfSDavid du Colombier 			reg.r[rd]);
5617dd7cddfSDavid du Colombier }
5627dd7cddfSDavid du Colombier 
5637dd7cddfSDavid du Colombier void
Imull(ulong inst)56480ee5cbfSDavid du Colombier Imull(ulong inst)
56580ee5cbfSDavid du Colombier {
56680ee5cbfSDavid du Colombier 	vlong v;
56780ee5cbfSDavid du Colombier 	int rs, rd, rm, rn;
56880ee5cbfSDavid du Colombier 
56980ee5cbfSDavid du Colombier 	rd = (inst>>16) & 0xf;
57080ee5cbfSDavid du Colombier 	rn = (inst>>12) & 0xf;
57180ee5cbfSDavid du Colombier 	rs = (inst>>8) & 0xf;
57280ee5cbfSDavid du Colombier 	rm = inst & 0xf;
57380ee5cbfSDavid du Colombier 
57480ee5cbfSDavid du Colombier 	if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC
57580ee5cbfSDavid du Colombier 	|| rd == rm || rn == rm || rd == rn)
57680ee5cbfSDavid du Colombier 		undef(inst);
57780ee5cbfSDavid du Colombier 
57880ee5cbfSDavid du Colombier 	if(inst & (1<<22)){
57980ee5cbfSDavid du Colombier 		v = (vlong)reg.r[rm] * (vlong)reg.r[rs];
58080ee5cbfSDavid du Colombier 		if(inst & (1 << 21))
58180ee5cbfSDavid du Colombier 			v += reg.r[rn];
58280ee5cbfSDavid du Colombier 	}else{
58380ee5cbfSDavid du Colombier 		v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs];
58480ee5cbfSDavid du Colombier 		if(inst & (1 << 21))
58580ee5cbfSDavid du Colombier 			v += (ulong)reg.r[rn];
58680ee5cbfSDavid du Colombier 	}
58780ee5cbfSDavid du Colombier 	reg.r[rd] = v >> 32;
58880ee5cbfSDavid du Colombier 	reg.r[rn] = v;
58980ee5cbfSDavid du Colombier 
59080ee5cbfSDavid du Colombier 	if(trace)
59180ee5cbfSDavid du Colombier 		itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx",
59280ee5cbfSDavid du Colombier 			reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
59380ee5cbfSDavid du Colombier 			v);
59480ee5cbfSDavid du Colombier }
59580ee5cbfSDavid du Colombier 
59680ee5cbfSDavid du Colombier void
Imula(ulong inst)5977dd7cddfSDavid du Colombier Imula(ulong inst)
5987dd7cddfSDavid du Colombier {
5997dd7cddfSDavid du Colombier 	int rs, rd, rm, rn;
6007dd7cddfSDavid du Colombier 
6017dd7cddfSDavid du Colombier 	rd = (inst>>16) & 0xf;
6027dd7cddfSDavid du Colombier 	rn = (inst>>12) & 0xf;
6037dd7cddfSDavid du Colombier 	rs = (inst>>8) & 0xf;
6047dd7cddfSDavid du Colombier 	rm = inst & 0xf;
6057dd7cddfSDavid du Colombier 
6067dd7cddfSDavid du Colombier 	if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm)
6077dd7cddfSDavid du Colombier 		undef(inst);
6087dd7cddfSDavid du Colombier 
6097dd7cddfSDavid du Colombier 	reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn];
6107dd7cddfSDavid du Colombier 
6117dd7cddfSDavid du Colombier 	if(trace)
6127dd7cddfSDavid du Colombier 		itrace("%s%s\tR%d,R%d,R%d,R%d =#%x",
6137dd7cddfSDavid du Colombier 			reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
6147dd7cddfSDavid du Colombier 			reg.r[rd]);
6157dd7cddfSDavid du Colombier }
6167dd7cddfSDavid du Colombier 
6177dd7cddfSDavid du Colombier void
Iswap(ulong inst)6187dd7cddfSDavid du Colombier Iswap(ulong inst)
6197dd7cddfSDavid du Colombier {
62059cc4ca5SDavid du Colombier 	int rn, rd, rm;
62159cc4ca5SDavid du Colombier 	ulong address, value, bbit;
62259cc4ca5SDavid du Colombier 
62359cc4ca5SDavid du Colombier 	bbit = inst & (1<<22);
62459cc4ca5SDavid du Colombier 	rn = (inst>>16) & 0xf;
62559cc4ca5SDavid du Colombier 	rd = (inst>>12) & 0xf;
62659cc4ca5SDavid du Colombier 	rm = (inst>>0) & 0xf;
62759cc4ca5SDavid du Colombier 
62859cc4ca5SDavid du Colombier 	address = reg.r[rn];
62959cc4ca5SDavid du Colombier 	if(bbit) {
63059cc4ca5SDavid du Colombier 		value = getmem_b(address);
63159cc4ca5SDavid du Colombier 		putmem_b(address, reg.r[rm]);
63259cc4ca5SDavid du Colombier 	} else {
63359cc4ca5SDavid du Colombier 		value = getmem_w(address);
63459cc4ca5SDavid du Colombier 		putmem_w(address, reg.r[rm]);
63559cc4ca5SDavid du Colombier 	}
63659cc4ca5SDavid du Colombier 	reg.r[rd] = value;
63759cc4ca5SDavid du Colombier 
63859cc4ca5SDavid du Colombier 	if(trace) {
63959cc4ca5SDavid du Colombier 		char *bw, *dotc;
64059cc4ca5SDavid du Colombier 
64159cc4ca5SDavid du Colombier 		bw = "";
64259cc4ca5SDavid du Colombier 		if(bbit)
64359cc4ca5SDavid du Colombier 			bw = "B";
64459cc4ca5SDavid du Colombier 		dotc = cond[reg.cond];
64559cc4ca5SDavid du Colombier 
64659cc4ca5SDavid du Colombier 		itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x",
64759cc4ca5SDavid du Colombier 			bw, dotc,
64859cc4ca5SDavid du Colombier 			rn, rd,
64959cc4ca5SDavid du Colombier 			address, value);
65059cc4ca5SDavid du Colombier 	}
6517dd7cddfSDavid du Colombier }
6527dd7cddfSDavid du Colombier 
65359cc4ca5SDavid du Colombier /*
65459cc4ca5SDavid du Colombier  * load/store word/byte
65559cc4ca5SDavid du Colombier  */
6567dd7cddfSDavid du Colombier void
Imem1(ulong inst)65759cc4ca5SDavid du Colombier Imem1(ulong inst)
6587dd7cddfSDavid du Colombier {
6597dd7cddfSDavid du Colombier 	int rn, rd, off, rm, sc, st;
6607dd7cddfSDavid du Colombier 	ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25;
6617dd7cddfSDavid du Colombier 
6627dd7cddfSDavid du Colombier 	bit25 = inst & (1<<25);
6637dd7cddfSDavid du Colombier 	pbit = inst & (1<<24);
6647dd7cddfSDavid du Colombier 	ubit = inst & (1<<23);
6657dd7cddfSDavid du Colombier 	bbit = inst & (1<<22);
6667dd7cddfSDavid du Colombier 	wbit = inst & (1<<21);
6677dd7cddfSDavid du Colombier 	lbit = inst & (1<<20);
6687dd7cddfSDavid du Colombier 	rn = (inst>>16) & 0xf;
6697dd7cddfSDavid du Colombier 	rd = (inst>>12) & 0xf;
6707dd7cddfSDavid du Colombier 
6717dd7cddfSDavid du Colombier 	SET(st);
6727dd7cddfSDavid du Colombier 	SET(sc);
6737dd7cddfSDavid du Colombier 	SET(rm);
6747dd7cddfSDavid du Colombier 	if(bit25) {
6757dd7cddfSDavid du Colombier 		rm = inst & 0xf;
6767dd7cddfSDavid du Colombier 		st = (inst>>5) & 0x3;
6777dd7cddfSDavid du Colombier 		sc = (inst>>7) & 0x1f;
6787dd7cddfSDavid du Colombier 		off = reg.r[rm];
6797dd7cddfSDavid du Colombier 		if(rm == REGPC)
6807dd7cddfSDavid du Colombier 			off += 8;
681*9a747e4fSDavid du Colombier 		off = shift(off, st, sc, 0);
6827dd7cddfSDavid du Colombier 	} else {
6837dd7cddfSDavid du Colombier 		off = inst & 0xfff;
6847dd7cddfSDavid du Colombier 	}
6857dd7cddfSDavid du Colombier 	if(!ubit)
6867dd7cddfSDavid du Colombier 		off = -off;
6877dd7cddfSDavid du Colombier 	if(rn == REGPC)
6887dd7cddfSDavid du Colombier 		off += 8;
6897dd7cddfSDavid du Colombier 
6907dd7cddfSDavid du Colombier 	address = reg.r[rn];
6917dd7cddfSDavid du Colombier 	if(pbit)
6927dd7cddfSDavid du Colombier 		address += off;
6937dd7cddfSDavid du Colombier 
6947dd7cddfSDavid du Colombier 	if(lbit) {
6957dd7cddfSDavid du Colombier 		if(bbit)
6967dd7cddfSDavid du Colombier 			value = getmem_b(address);
6977dd7cddfSDavid du Colombier 		else
6987dd7cddfSDavid du Colombier 			value = getmem_w(address);
6997dd7cddfSDavid du Colombier 		if(rd == REGPC)
7007dd7cddfSDavid du Colombier 			value -= 4;
7017dd7cddfSDavid du Colombier 		reg.r[rd] = value;
7027dd7cddfSDavid du Colombier 	} else {
7037dd7cddfSDavid du Colombier 		value = reg.r[rd];
7047dd7cddfSDavid du Colombier 		if(rd == REGPC)
7057dd7cddfSDavid du Colombier 			value -= 4;
7067dd7cddfSDavid du Colombier 		if(bbit)
7077dd7cddfSDavid du Colombier 			putmem_b(address, value);
7087dd7cddfSDavid du Colombier 		else
7097dd7cddfSDavid du Colombier 			putmem_w(address, value);
7107dd7cddfSDavid du Colombier 	}
7117dd7cddfSDavid du Colombier 	if(!(pbit && !wbit))
7127dd7cddfSDavid du Colombier 		reg.r[rn] += off;
7137dd7cddfSDavid du Colombier 
7147dd7cddfSDavid du Colombier 	if(trace) {
71559cc4ca5SDavid du Colombier 		char *bw, *dotp, *dotc;
71659cc4ca5SDavid du Colombier 
71759cc4ca5SDavid du Colombier 		bw = "W";
71859cc4ca5SDavid du Colombier 		if(bbit)
71959cc4ca5SDavid du Colombier 			bw = "BU";
72059cc4ca5SDavid du Colombier 		dotp = "";
72159cc4ca5SDavid du Colombier 		if(!pbit)
72259cc4ca5SDavid du Colombier 			dotp = ".P";
72359cc4ca5SDavid du Colombier 		dotc = cond[reg.cond];
72459cc4ca5SDavid du Colombier 
7257dd7cddfSDavid du Colombier 		if(lbit) {
7267dd7cddfSDavid du Colombier 			if(!bit25)
72759cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
72859cc4ca5SDavid du Colombier 					bw, dotp, dotc,
7297dd7cddfSDavid du Colombier 					off, rn, rd,
7307dd7cddfSDavid du Colombier 					address, value);
7317dd7cddfSDavid du Colombier 			else
73259cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d  #%lux=#%x",
73359cc4ca5SDavid du Colombier 					bw, dotp, dotc,
7347dd7cddfSDavid du Colombier 					rm, shtype[st], sc, rn, rd,
7357dd7cddfSDavid du Colombier 					address, value);
7367dd7cddfSDavid du Colombier 		} else {
7377dd7cddfSDavid du Colombier 			if(!bit25)
73859cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
73959cc4ca5SDavid du Colombier 					bw, dotp, dotc,
7407dd7cddfSDavid du Colombier 					rd, off, rn,
7417dd7cddfSDavid du Colombier 					address, value);
7427dd7cddfSDavid du Colombier 			else
74359cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x",
74459cc4ca5SDavid du Colombier 					bw, dotp, dotc,
7457dd7cddfSDavid du Colombier 					rd, rm, shtype[st], sc, rn,
7467dd7cddfSDavid du Colombier 					address, value);
7477dd7cddfSDavid du Colombier 		}
7487dd7cddfSDavid du Colombier 	}
7497dd7cddfSDavid du Colombier }
7507dd7cddfSDavid du Colombier 
75159cc4ca5SDavid du Colombier /*
75259cc4ca5SDavid du Colombier  * load/store unsigned byte/half word
75359cc4ca5SDavid du Colombier  */
75459cc4ca5SDavid du Colombier void
Imem2(ulong inst)75559cc4ca5SDavid du Colombier Imem2(ulong inst)
75659cc4ca5SDavid du Colombier {
75759cc4ca5SDavid du Colombier 	int rn, rd, off, rm;
75859cc4ca5SDavid du Colombier 	ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22;
75959cc4ca5SDavid du Colombier 
76059cc4ca5SDavid du Colombier 	pbit = inst & (1<<24);
76159cc4ca5SDavid du Colombier 	ubit = inst & (1<<23);
76259cc4ca5SDavid du Colombier 	bit22 = inst & (1<<22);
76359cc4ca5SDavid du Colombier 	wbit = inst & (1<<21);
76459cc4ca5SDavid du Colombier 	lbit = inst & (1<<20);
76559cc4ca5SDavid du Colombier 	sbit = inst & (1<<6);
76659cc4ca5SDavid du Colombier 	hbit = inst & (1<<5);
76759cc4ca5SDavid du Colombier 	rn = (inst>>16) & 0xf;
76859cc4ca5SDavid du Colombier 	rd = (inst>>12) & 0xf;
76959cc4ca5SDavid du Colombier 
77059cc4ca5SDavid du Colombier 	SET(rm);
77159cc4ca5SDavid du Colombier 	if(bit22) {
77259cc4ca5SDavid du Colombier 		off = ((inst>>4) & 0xf0) | (inst & 0xf);
77359cc4ca5SDavid du Colombier 	} else {
77459cc4ca5SDavid du Colombier 		rm = inst & 0xf;
77559cc4ca5SDavid du Colombier 		off = reg.r[rm];
77659cc4ca5SDavid du Colombier 		if(rm == REGPC)
77759cc4ca5SDavid du Colombier 			off += 8;
77859cc4ca5SDavid du Colombier 	}
77959cc4ca5SDavid du Colombier 	if(!ubit)
78059cc4ca5SDavid du Colombier 		off = -off;
78159cc4ca5SDavid du Colombier 	if(rn == REGPC)
78259cc4ca5SDavid du Colombier 		off += 8;
78359cc4ca5SDavid du Colombier 
78459cc4ca5SDavid du Colombier 	address = reg.r[rn];
78559cc4ca5SDavid du Colombier 	if(pbit)
78659cc4ca5SDavid du Colombier 		address += off;
78759cc4ca5SDavid du Colombier 
78859cc4ca5SDavid du Colombier 	if(lbit) {
78959cc4ca5SDavid du Colombier 		if(hbit) {
79059cc4ca5SDavid du Colombier 			value = getmem_h(address);
79159cc4ca5SDavid du Colombier 			if(sbit && (value & 0x8000))
79259cc4ca5SDavid du Colombier 				value |= 0xffff0000;
79359cc4ca5SDavid du Colombier 		} else {
79459cc4ca5SDavid du Colombier 			value = getmem_b(address);
79559cc4ca5SDavid du Colombier 			if(value & 0x80)
79659cc4ca5SDavid du Colombier 				value |= 0xffffff00;
79759cc4ca5SDavid du Colombier 		}
79859cc4ca5SDavid du Colombier 		if(rd == REGPC)
79959cc4ca5SDavid du Colombier 			value -= 4;
80059cc4ca5SDavid du Colombier 		reg.r[rd] = value;
80159cc4ca5SDavid du Colombier 	} else {
80259cc4ca5SDavid du Colombier 		value = reg.r[rd];
80359cc4ca5SDavid du Colombier 		if(rd == REGPC)
80459cc4ca5SDavid du Colombier 			value -= 4;
80559cc4ca5SDavid du Colombier 		if(hbit) {
80659cc4ca5SDavid du Colombier 			putmem_h(address, value);
80759cc4ca5SDavid du Colombier 		} else {
80859cc4ca5SDavid du Colombier 			putmem_b(address, value);
80959cc4ca5SDavid du Colombier 		}
81059cc4ca5SDavid du Colombier 	}
81159cc4ca5SDavid du Colombier 	if(!(pbit && !wbit))
81259cc4ca5SDavid du Colombier 		reg.r[rn] += off;
81359cc4ca5SDavid du Colombier 
81459cc4ca5SDavid du Colombier 	if(trace) {
81559cc4ca5SDavid du Colombier 		char *hb, *dotp, *dotc;
81659cc4ca5SDavid du Colombier 
81759cc4ca5SDavid du Colombier 		hb = "B";
81859cc4ca5SDavid du Colombier 		if(hbit)
81959cc4ca5SDavid du Colombier 			hb = "H";
82059cc4ca5SDavid du Colombier 		dotp = "";
82159cc4ca5SDavid du Colombier 		if(!pbit)
82259cc4ca5SDavid du Colombier 			dotp = ".P";
82359cc4ca5SDavid du Colombier 		dotc = cond[reg.cond];
82459cc4ca5SDavid du Colombier 
82559cc4ca5SDavid du Colombier 		if(lbit) {
82659cc4ca5SDavid du Colombier 			if(bit22)
82759cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
82859cc4ca5SDavid du Colombier 					hb, dotp, dotc,
82959cc4ca5SDavid du Colombier 					off, rn, rd,
83059cc4ca5SDavid du Colombier 					address, value);
83159cc4ca5SDavid du Colombier 			else
83259cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\t(R%d)(R%d),R%d  #%lux=#%x",
83359cc4ca5SDavid du Colombier 					hb, dotp, dotc,
83459cc4ca5SDavid du Colombier 					rm, rn, rd,
83559cc4ca5SDavid du Colombier 					address, value);
83659cc4ca5SDavid du Colombier 		} else {
83759cc4ca5SDavid du Colombier 			if(bit22)
83859cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
83959cc4ca5SDavid du Colombier 					hb, dotp, dotc,
84059cc4ca5SDavid du Colombier 					rd, off, rn,
84159cc4ca5SDavid du Colombier 					address, value);
84259cc4ca5SDavid du Colombier 			else
84359cc4ca5SDavid du Colombier 				itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x",
84459cc4ca5SDavid du Colombier 					hb, dotp, dotc,
84559cc4ca5SDavid du Colombier 					rd, rm, rn,
84659cc4ca5SDavid du Colombier 					address, value);
84759cc4ca5SDavid du Colombier 		}
84859cc4ca5SDavid du Colombier 	}
84959cc4ca5SDavid du Colombier }
85059cc4ca5SDavid du Colombier 
8517dd7cddfSDavid du Colombier void
Ilsm(ulong inst)8527dd7cddfSDavid du Colombier Ilsm(ulong inst)
8537dd7cddfSDavid du Colombier {
8547dd7cddfSDavid du Colombier 	char pbit, ubit, sbit, wbit, lbit;
8557dd7cddfSDavid du Colombier 	int i, rn, reglist;
8567dd7cddfSDavid du Colombier 	ulong address, predelta, postdelta;
8577dd7cddfSDavid du Colombier 
8587dd7cddfSDavid du Colombier 	pbit = (inst>>24) & 0x1;
8597dd7cddfSDavid du Colombier 	ubit = (inst>>23) & 0x1;
8607dd7cddfSDavid du Colombier 	sbit = (inst>>22) & 0x1;
8617dd7cddfSDavid du Colombier 	wbit = (inst>>21) & 0x1;
8627dd7cddfSDavid du Colombier 	lbit = (inst>>20) & 0x1;
8637dd7cddfSDavid du Colombier 	rn =   (inst>>16) & 0xf;
8647dd7cddfSDavid du Colombier 	reglist = inst & 0xffff;
8657dd7cddfSDavid du Colombier 
8667dd7cddfSDavid du Colombier 	if(reglist & 0x8000)
8677dd7cddfSDavid du Colombier 		undef(reg.ir);
8687dd7cddfSDavid du Colombier 	if(sbit)
8697dd7cddfSDavid du Colombier 		undef(reg.ir);
8707dd7cddfSDavid du Colombier 
8717dd7cddfSDavid du Colombier 	address = reg.r[rn];
8727dd7cddfSDavid du Colombier 
8737dd7cddfSDavid du Colombier 	if(pbit) {
8747dd7cddfSDavid du Colombier 		predelta = 4;
8757dd7cddfSDavid du Colombier 		postdelta = 0;
8767dd7cddfSDavid du Colombier 	} else {
8777dd7cddfSDavid du Colombier 		predelta = 0;
8787dd7cddfSDavid du Colombier 		postdelta = 4;
8797dd7cddfSDavid du Colombier 	}
8807dd7cddfSDavid du Colombier 	if(ubit) {
8817dd7cddfSDavid du Colombier 		for (i = 0; i < 16; ++i) {
8827dd7cddfSDavid du Colombier 			if(!(reglist & (1 << i)))
8837dd7cddfSDavid du Colombier 				continue;
8847dd7cddfSDavid du Colombier 			address += predelta;
8857dd7cddfSDavid du Colombier 			if(lbit)
8867dd7cddfSDavid du Colombier 				reg.r[i] = getmem_w(address);
8877dd7cddfSDavid du Colombier 			else
8887dd7cddfSDavid du Colombier 				putmem_w(address, reg.r[i]);
8897dd7cddfSDavid du Colombier 			address += postdelta;
8907dd7cddfSDavid du Colombier 		}
8917dd7cddfSDavid du Colombier 	} else {
8927dd7cddfSDavid du Colombier 		for (i = 15; 0 <= i; --i) {
8937dd7cddfSDavid du Colombier 			if(!(reglist & (1 << i)))
8947dd7cddfSDavid du Colombier 				continue;
8957dd7cddfSDavid du Colombier 			address -= predelta;
8967dd7cddfSDavid du Colombier 			if(lbit)
8977dd7cddfSDavid du Colombier 				reg.r[i] = getmem_w(address);
8987dd7cddfSDavid du Colombier 			else
8997dd7cddfSDavid du Colombier 				putmem_w(address, reg.r[i]);
9007dd7cddfSDavid du Colombier 			address -= postdelta;
9017dd7cddfSDavid du Colombier 		}
9027dd7cddfSDavid du Colombier 	}
9037dd7cddfSDavid du Colombier 	if(wbit) {
9047dd7cddfSDavid du Colombier 		reg.r[rn] = address;
9057dd7cddfSDavid du Colombier 	}
9067dd7cddfSDavid du Colombier 
9077dd7cddfSDavid du Colombier 	if(trace) {
9087dd7cddfSDavid du Colombier 		itrace("%s.%c%c\tR%d=%lux%s, <%lux>",
9097dd7cddfSDavid du Colombier 			(lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'),
9107dd7cddfSDavid du Colombier 			rn, reg.r[rn], (wbit ? "!" : ""), reglist);
9117dd7cddfSDavid du Colombier 	}
9127dd7cddfSDavid du Colombier }
9137dd7cddfSDavid du Colombier 
9147dd7cddfSDavid du Colombier void
Ib(ulong inst)9157dd7cddfSDavid du Colombier Ib(ulong inst)
9167dd7cddfSDavid du Colombier {
9177dd7cddfSDavid du Colombier 	long v;
9187dd7cddfSDavid du Colombier 
9197dd7cddfSDavid du Colombier 	v = inst & 0xffffff;
9207dd7cddfSDavid du Colombier 	v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
9217dd7cddfSDavid du Colombier 	if(trace)
9227dd7cddfSDavid du Colombier 		itrace("B%s\t#%lux", cond[reg.cond], v);
9237dd7cddfSDavid du Colombier 	reg.r[REGPC] = v - 4;
9247dd7cddfSDavid du Colombier }
9257dd7cddfSDavid du Colombier 
9267dd7cddfSDavid du Colombier void
Ibl(ulong inst)9277dd7cddfSDavid du Colombier Ibl(ulong inst)
9287dd7cddfSDavid du Colombier {
9297dd7cddfSDavid du Colombier 	long v;
9307dd7cddfSDavid du Colombier 	Symbol s;
9317dd7cddfSDavid du Colombier 
9327dd7cddfSDavid du Colombier 	v = inst & 0xffffff;
9337dd7cddfSDavid du Colombier 	v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
9347dd7cddfSDavid du Colombier 	if(trace)
9357dd7cddfSDavid du Colombier 		itrace("BL%s\t#%lux", cond[reg.cond], v);
9367dd7cddfSDavid du Colombier 
9377dd7cddfSDavid du Colombier 	if(calltree) {
9387dd7cddfSDavid du Colombier 		findsym(v, CTEXT, &s);
9397dd7cddfSDavid du Colombier 		Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name);
9407dd7cddfSDavid du Colombier 		printparams(&s, reg.r[13]);
9417dd7cddfSDavid du Colombier 		Bprint(bioout, "from ");
9427dd7cddfSDavid du Colombier 		printsource(reg.r[REGPC]);
9437dd7cddfSDavid du Colombier 		Bputc(bioout, '\n');
9447dd7cddfSDavid du Colombier 	}
9457dd7cddfSDavid du Colombier 
9467dd7cddfSDavid du Colombier 	reg.r[REGLINK] = reg.r[REGPC] + 4;
9477dd7cddfSDavid du Colombier 	reg.r[REGPC] = v - 4;
9487dd7cddfSDavid du Colombier }
949