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