1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: 17: 18: 19: 20:
21:
22: #include "../cmdsvc.h"
23:
24: #define aINSTSZ 4
25: #define tINSTSZ 2
26: #define REGBIT(reg) (1 << (reg))
27: #define REGSZ 4
28: #define regPC 15
29: #define regSP 13
30:
31: LOCAL UW curCPSR;
32: LOCAL UW nextPC;
33: LOCAL W nextLen;
34: LOCAL UW repInst;
35: LOCAL W repReg;
36: LOCAL W trcNext;
37:
38: 39: 40:
41: LOCAL UW getInstField(UW mask, W sht)
42: {
43: return (repInst & mask) >> sht;
44: }
45: 46: 47:
48: LOCAL void setRepInst(UW mask, W sht)
49: {
50: repInst = (repInst & ~mask) | ((repReg & 0xF) << sht);
51: }
52: 53: 54:
55: LOCAL W getRepReg(UW reg)
56: {
57: W i;
58:
59: for (i = 0; i < 16 && (reg & 0x1); i++, reg >>= 1);
60: return i + 0x10;
61: }
62: 63: 64:
65: LOCAL W checkCond(W cond)
66: {
67: UW sr = curCPSR;
68:
69: switch(cond) {
70: case 0:
71: if (sr & PSR_Z) return 1; break;
72: case 1:
73: if (!(sr & PSR_Z)) return 1; break;
74: case 2:
75: if (sr & PSR_C) return 1; break;
76: case 3:
77: if (!(sr & PSR_C)) return 1; break;
78: case 4:
79: if (sr & PSR_N) return 1; break;
80: case 5:
81: if (!(sr & PSR_N)) return 1; break;
82: case 6:
83: if (sr & PSR_V) return 1; break;
84: case 7:
85: if (!(sr & PSR_V)) return 1; break;
86: case 8:
87: if ((sr & (PSR_C | PSR_Z)) == PSR_C) return 1; break;
88: case 9:
89: if (!(sr& PSR_C) || (sr & PSR_Z)) return 1; break;
90: case 12:
91: if (sr & PSR_Z) return 0;
92: case 10:
93: sr &= PSR_N | PSR_V;
94: if (sr == 0 || sr == (PSR_N | PSR_V)) return 1; break;
95: case 13:
96: if (sr & PSR_Z) return 1;
97: case 11:
98: sr &= PSR_N | PSR_V;
99: if (sr == PSR_N || sr == PSR_V) return 1; break;
100: case 14:
101: case 15:
102: return 1;
103: }
104: return 0;
105: }
106: 107: 108:
109: LOCAL void noBranch(UW inst)
110: {
111: }
112: 113: 114:
115: LOCAL void armBInst(UW inst)
116: {
117: W off;
118:
119:
120: if (trcNext) {
121: if (inst & 0x01000000) return;
122: if (inst >= 0xF0000000) return;
123: }
124: off = (inst & 0x00FFFFFF) << 2;
125: if (off & 0x02000000) off -= 0x04000000;
126: nextPC += aINSTSZ + off;
127:
128: if (inst >= 0xF0000000) {
129: nextPC += getInstField(0x01000000, 24) << 1;
130:
131: nextLen = tINSTSZ;
132: }
133: }
134: 135: 136:
137: LOCAL void armBxInst(UW inst)
138: {
139:
140: if (trcNext) {
141: if (inst & 0x00000020) return;
142: }
143: inst &= 0x0000000F;
144: if (inst == regPC) {
145: nextPC += aINSTSZ;
146: } else {
147: nextPC = getRegister(inst);
148: }
149: if (nextPC & 1) nextLen = tINSTSZ;
150: }
151: 152: 153:
154: LOCAL void armOpInst(UW inst)
155: {
156: W rn, rm;
157: UW usereg;
158:
159:
160: rm = inst & 0x01E00000;
161: if (rm >= 0x01000000 && rm <= 0x01600000) return;
162:
163:
164: rn = getInstField(0x000F0000, 16);
165: usereg = REGBIT(rn);
166:
167:
168: if (!(inst & 0x02000000)) {
169: rm = getInstField(0x0000000F, 0);
170: usereg |= REGBIT(rm);
171: if (inst & 0x00000010)
172: usereg |= REGBIT(getInstField(0x00000F00, 8));
173: }
174:
175: repReg = getRepReg(usereg);
176:
177:
178: setRepInst(0x0000F000, 12);
179:
180:
181: if (rn == regPC) setRepInst(0x000F0000, 16);
182:
183:
184: if (rm == regPC) setRepInst(0x0000000F, 0);
185:
186:
187: if ((inst & 0x00100000) && (getCurSPSR() & PSR_T)) nextLen = tINSTSZ;
188: }
189: 190: 191:
192: LOCAL void armLdrInst(UW inst)
193: {
194: W rn, roff;
195: UW usereg;
196:
197:
198: rn = getInstField(0x000F0000, 16);
199: usereg = REGBIT(rn);
200:
201:
202: roff = 0;
203: if (inst & 0x02000000) {
204: roff = getInstField(0x0000000F, 0);
205: usereg |= REGBIT(roff);
206: }
207:
208:
209: repReg = getRepReg(usereg);
210:
211:
212: setRepInst(0x0000F000, 12);
213:
214:
215: if (rn == regPC) setRepInst(0x000F0000, 16);
216:
217:
218: if (roff == regPC) setRepInst(0x0000000F, 0);
219: }
220: 221: 222:
223: LOCAL void armLdmInst(UW inst)
224: {
225: W i, off;
226: UW baddr;
227:
228:
229: baddr = getRegister(getInstField(0x000F0000, 16));
230:
231:
232: off = (inst & 0x01000000) ? REGSZ : 0;
233:
234: if (inst & 0x00800000) {
235: for (i = 0; i < regPC; i++) {
236: if (inst & REGBIT(i)) off += REGSZ;
237: }
238: baddr += off;
239: } else {
240: baddr -= off;
241: }
242:
243:
244: readMem(baddr, &nextPC, REGSZ, 2);
245:
246:
247: if ((inst & 0x00400000) && (getCurSPSR() & PSR_T)) nextLen = tINSTSZ;
248: }
249: 250: 251:
252: LOCAL void armMrcsInst(UW inst)
253: {
254:
255: repReg = getRepReg(0);
256:
257:
258: setRepInst(0x0000F000, 12);
259: }
260: #if CPU_ARMv6
261: 262: 263:
264: LOCAL void armRfeInst(UW inst)
265: {
266: W off;
267: UW baddr, saddr, paddr, spsr;
268:
269:
270: baddr = getRegister(getInstField(0x000F0000, 16));
271:
272:
273: off = (inst & 0x01000000) ? REGSZ : 0;
274:
275: if (inst & 0x00800000) {
276: paddr = baddr + off;
277: saddr = baddr + off + REGSZ;
278: } else {
279: paddr = baddr - off - REGSZ;
280: saddr = baddr - off;
281: }
282:
283:
284: readMem(paddr, &nextPC, REGSZ, 2);
285:
286:
287: readMem(saddr, &spsr, REGSZ, 2);
288: if (spsr & PSR_T) nextLen = tINSTSZ;
289: }
290: #endif
291: 292: 293:
294: LOCAL void thumbBcondInst(UW inst)
295: {
296: W cond, off;
297:
298: cond = getInstField(0x0F00, 8);
299:
300:
301: if (cond == 14) return;
302:
303:
304: if (!checkCond(cond)) return;
305:
306: off = (inst & 0x00FF) << 1;
307: if (off >= 0x100) off -= 0x200;
308: nextPC += tINSTSZ + off;
309: }
310: 311: 312:
313: LOCAL void thumbBInst(UW inst)
314: {
315: W off;
316:
317: off = (inst & 0x07FF) << 1;
318: if (off >= 0x800) off -= 0x1000;
319: nextPC += tINSTSZ + off;
320: }
321: 322: 323:
324: LOCAL void thumbBxInst(UW inst)
325: {
326:
327: if (inst & 0x0080) {
328: if (trcNext) return;
329: }
330: inst = getInstField(0x0078, 3);
331: if (inst == regPC) {
332: nextPC += tINSTSZ;
333: } else {
334: nextPC = getRegister(inst);
335: }
336: if (!(nextPC & 1)) nextLen = aINSTSZ;
337: }
338: 339: 340:
341: LOCAL void thumbBlInst(UW inst)
342: {
343: W off;
344: UH inst2;
345:
346:
347: if (trcNext) return;
348:
349:
350: readMem(nextPC, &inst2, tINSTSZ, 2);
351:
352: off = (inst & 0x07FF) << 12;
353: if (off >= 0x400000) off -= 0x800000;
354: nextPC += tINSTSZ + off + ((inst2 & 0x07FF) << 1);
355: if (!(inst2 & 0x1000)) nextLen = aINSTSZ;
356: }
357: 358: 359:
360: LOCAL void thumbOp6Inst(UW inst)
361: {
362: UW op, dreg, mreg;
363:
364: op = inst & 0x0300;
365: if (op == 0x0100) return;
366:
367: dreg = getInstField(0x0007, 0);
368: if (inst & 0x0080) dreg |= 0x8;
369: if (dreg != regPC) return;
370:
371: mreg = getInstField(0x0078, 3);
372: nextPC = getRegister(mreg) & ~(tINSTSZ - 1);
373:
374:
375: if (op == 0x0000) nextPC += getRegister(dreg);
376: }
377: 378: 379:
380: LOCAL void thumbPopInst(UW inst)
381: {
382: W i;
383: UW sp;
384:
385: sp = getRegister(regSP);
386: for (i = 0; i < 8; i++) {
387: if (inst & REGBIT(i)) sp += REGSZ;
388: }
389:
390: readMem(sp, &nextPC, REGSZ, 2);
391: }
392:
393:
394: typedef struct {
395: UW mask;
396: UW code;
397: void (*calcNextPC)(UW inst);
398: } INST_T;
399:
400: LOCAL const INST_T instArm[] = {
401: { 0xFFFFFFFF, 0xE1A00000, noBranch},
402: { 0xFFF000F0, 0xE1200070, noBranch},
403: { 0x0FFFFFF0, 0x012FFF10, armBxInst},
404: { 0xFE000000, 0xFA000000, armBInst},
405: { 0x0FF000F0, 0x01200030, armBxInst},
406: { 0x0E000000, 0x0A000000, armBInst},
407: { 0x0F000000, 0x0F000000, noBranch},
408: { 0x0C10F000, 0x0410F000, armLdrInst},
409: { 0x0E108000, 0x08108000, armLdmInst},
410:
411:
412: { 0x0F10F010, 0x0E10F010, armMrcsInst},
413: { 0x0FBFFFFF, 0x010FF000, armMrcsInst},
414:
415: { 0x0E000090, 0x00000090, noBranch},
416:
417:
418: { 0x0C00F000, 0x0000F000, armOpInst},
419: #if CPU_ARMv6
420: { 0xFE50FFFF, 0xF8100A00, armRfeInst},
421: #endif
422: { 0 }
423: };
424:
425:
426: LOCAL const INST_T instThumb[] = {
427:
428: { 0xFF00, 0xBE00, noBranch},
429: { 0xFFFF, 0x46C0, noBranch},
430: { 0xFF00, 0xDF00, noBranch},
431: { 0xF800, 0xE000, thumbBInst},
432: { 0xF000, 0xD000, thumbBcondInst},
433: { 0xF000, 0xF000, thumbBlInst},
434: { 0xFF80, 0x4780, thumbBxInst},
435: { 0xFF00, 0x4700, thumbBxInst},
436:
437:
438:
439:
440:
441: { 0xFC00, 0x4400, thumbOp6Inst},
442:
443:
444:
445:
446:
447:
448:
449:
450: { 0xFD00, 0xBD00, thumbPopInst},
451: { 0 }
452: };
453: 454: 455:
456: EXPORT W getStepAddr(UW pc, UW cpsr, W mode, UW* npc, UW *rep)
457: {
458: W len;
459: UW inst;
460: INST_T *tab;
461:
462:
463: len = (cpsr & PSR_T) ? tINSTSZ : aINSTSZ;
464: curCPSR = cpsr;
465: repReg = 0;
466: repInst = 0;
467: nextPC = pc + len;
468: nextLen = len;
469: trcNext = mode;
470:
471:
472: if (readMem(pc, &inst, len, 2) != len) goto EXIT;
473: repInst = inst;
474:
475: if (len == 4) {
476:
477: if (!checkCond(getInstField(0xF0000000, 28))) goto EXIT;
478: tab = (INST_T*)instArm;
479: } else {
480: tab = (INST_T*)instThumb;
481: inst &= 0xFFFF;
482: }
483:
484:
485: for ( ; tab->mask != 0; tab++) {
486: if ((inst & tab->mask) == tab->code) {
487: (*(tab->calcNextPC))(inst);
488: break;
489: }
490: }
491: EXIT:
492: *npc = nextPC & ~(nextLen - 1);
493: *rep = repInst;
494: return nextLen | (repReg << 4);
495: }