1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14:
15: 16: 17: 18: 19:
20:
21: #include "../cmdsvc.h"
22: #include <sys/sysinfo.h>
23:
24:
25: #define BREAK_ARM 0xE1200070
26: #define BREAK_THUMB 0xBE00
27:
28: 29: 30:
31: typedef struct {
32: UW addr;
33: UW code;
34: UW atr;
35: H sz;
36: UB cmd[L_BPCMD];
37: } BRKPT;
38:
39: #define MAX_SBP (8)
40: #define MAX_IBP (0)
41: #define MAX_OBP (0)
42: #define MAX_BRKPT (MAX_SBP + MAX_IBP + MAX_OBP)
43:
44: LOCAL BRKPT brkPt[MAX_BRKPT + 1];
45:
46:
47: 48: 49: 50:
51: typedef struct {
52: UW addr;
53: UW code;
54: UW pc;
55: UW inst;
56: UW regval;
57: H reg;
58: H sz;
59: } STEPPT;
60:
61: LOCAL STEPPT stepPt;
62:
63: 64: 65:
66: #define BA_S 0x1000
67: #define BA_I 0x2000
68: #define BA_O 0x4000
69: #define BA_SET 0x8000
70: #define BA_PRE 0x0100
71: #define BA_R 0x0200
72: #define BA_W 0x0400
73: #define BA_RW 0x0600
74: #define BA_TMP 0x0800
75:
76: #define MAX_BPATR 1
77:
78: LOCAL const struct {
79: UB name[4];
80: UW atr;
81: } brkAtr[MAX_BPATR] = {
82: {"S ", 0x00000000 | BA_S | BA_PRE},
83: };
84:
85: 86: 87:
88: LOCAL W traceMode;
89: LOCAL W traceStep;
90: LOCAL W stepFlg;
91: LOCAL union {
92: UB b[8];
93: UW w[2];
94: } sbpCode;
95:
96: 97: 98:
99:
100: LOCAL void setDSCR(UW val) {return;}
101: LOCAL UW getDSCR(void) {return 0;}
102: LOCAL UW getWFAR(void) {return 0;}
103: LOCAL void setBVR(W num, UW val) {return;}
104: LOCAL void setBCR(W num, UW val) {return;}
105: LOCAL UW getBCR(W num) {return 0;}
106: LOCAL void setWVR(W num, UW val) {return;}
107: LOCAL void setWCR(W num, UW val) {return;}
108: LOCAL UW getWCR(W num) {return 0;}
109:
110: 111: 112:
113: LOCAL UW CheckCP14(void)
114: {
115: return getDSCR() & 0x00008000;
116: }
117: 118: 119:
120: LOCAL UW EnableCP14(void)
121: {
122: UW dscr;
123:
124: dscr = getDSCR();
125: dscr |= 0x00008000;
126: dscr &= ~0x00004000;
127: setDSCR(dscr);
128:
129:
130: return CheckCP14();
131: }
132: 133: 134:
135: LOCAL void DisableCP14(void)
136: {
137: setDSCR(getDSCR() & ~0x00008000);
138: return;
139: }
140: 141: 142:
143: EXPORT W getBreakAtr(UB *name)
144: {
145: W i;
146:
147: if (name[4] == ' ') {
148: for (i = 0; i < MAX_BPATR; i++) {
149: if (*((UW*)brkAtr[i].name) == *((UW*)name))
150: return brkAtr[i].atr;
151: }
152: }
153: return E_BPATR;
154: }
155: 156: 157:
158: LOCAL UB *strBreakAtr(W atr)
159: {
160: W i;
161: static UB str[5];
162:
163: atr &= ~BA_SET;
164:
165: for (i = 0; i < MAX_BPATR; i++) {
166: if (brkAtr[i].atr == atr) {
167: memcpy(str, brkAtr[i].name, 4);
168: for (i = 4; str[--i] == ' '; );
169: str[i + 1] = '\0';
170: return str;
171: }
172: }
173: return NULL;
174: }
175: 176: 177:
178: EXPORT ER setBreak(UW addr, W atr, UB *cmd, W cmdlen)
179: {
180: W ibcnt, obcnt, sbcnt, sz;
181: UW code;
182: BRKPT *bp, *p;
183:
184: if (atr == 0) atr = BA_S | BA_PRE;
185:
186:
187: sz = (addr & 0x03) ? 2 : 4;
188: addr &= ~(sz - 1);
189:
190: if (atr & BA_TMP) {
191: bp = &brkPt[MAX_BRKPT];
192: } else {
193:
194: ibcnt = obcnt = sbcnt = 0;
195: for (bp = NULL, p = brkPt; p < &brkPt[MAX_BRKPT]; p++) {
196: if (p->addr == 0) {if (bp == NULL) bp = p;}
197: else if (p->addr == addr) bp = p;
198: else if (p->atr & BA_O) obcnt++;
199: else if (p->atr & BA_I) ibcnt++;
200: else sbcnt++;
201: }
202:
203: if (atr & BA_O) {
204: if (obcnt >= MAX_OBP) return E_HBPOVR;
205: } else if (atr & BA_I) {
206: if (ibcnt >= MAX_IBP) return E_HBPOVR;
207: } else {
208: if (sbcnt >= MAX_SBP) return E_SBPOVR;
209: }
210: }
211:
212: if (atr & BA_S) {
213:
214:
215:
216:
217: if (readMem(addr, &code, sz, 2) != sz) return E_BPBAD;
218: if (writeMem(addr, &sbpCode.b[sz], sz, 2) != sz) return E_BPROM;
219: writeMem(addr, &code, sz, 2);
220: } else {
221: code = 0;
222: }
223:
224:
225: bp->addr = addr;
226: bp->atr = atr | BA_SET;
227: bp->sz = sz;
228: bp->code = code;
229: memset(bp->cmd, 0, L_BPCMD);
230: if (cmdlen > 0) memcpy(bp->cmd, cmd, cmdlen);
231: return E_OK;
232: }
233: 234: 235:
236: EXPORT ER clearBreak(UW addr)
237: {
238: BRKPT *p;
239:
240: if (addr == 0) {
241: memset(&brkPt[0], 0, sizeof(brkPt));
242: return E_OK;
243: }
244: for (p = brkPt; p < &brkPt[MAX_BRKPT]; p++) {
245: if (p->addr && p->addr == (addr & ~(p->sz - 1))) {
246: memset(p, 0, sizeof(BRKPT));
247: return E_OK;
248: }
249: }
250: return E_BPUDF;
251: }
252: 253: 254:
255: EXPORT void dspBreak(void)
256: {
257: BRKPT *p;
258:
259: for (p = brkPt; p < &brkPt[MAX_BRKPT]; p++) {
260: if (p->addr == 0) continue;
261:
262: DSP_F3(08X,(p->addr + ((p->sz & 2) >> 1)), CH,' ',
263: S,strBreakAtr(p->atr));
264: if (p->cmd[0] != '\0') {
265: DSP_F3(S," \"", S,p->cmd, CH,'"');
266: }
267: DSP_LF;
268: }
269: }
270: 271: 272:
273: EXPORT void initBreak(void)
274: {
275:
276: memset(&brkPt[0], 0, sizeof(brkPt));
277:
278:
279: memset(&stepPt, 0, sizeof(stepPt));
280:
281:
282: traceMode = traceStep = stepFlg = 0;
283:
284:
285: *((UH*)&sbpCode.b[2]) = BREAK_THUMB;
286: *((UW*)&sbpCode.b[4]) = BREAK_ARM;
287: }
288: 289: 290:
291: EXPORT W resetBreak(UW vec)
292: {
293: W i, n, bpflg;
294: UW code, pc;
295: BRKPT *p;
296:
297: pc = getCurPCX();
298: bpflg = 0;
299:
300:
301: if (CheckCP14()) {
302:
303: for (i = 0; i < MAX_IBP; i++) {
304: setBCR(i, getBCR(i) & ~1);
305: }
306:
307:
308: for (i = 0; i < MAX_OBP; i++) {
309: setWCR(i, getWCR(i) & ~1);
310: }
311:
312:
313: }
314:
315:
316: if (stepPt.addr != 0) {
317: n = stepPt.sz;
318: readMem(stepPt.addr, &code, n, 2);
319: if (memcmp(&code, &sbpCode.b[n], n) == 0) {
320: if (pc == stepPt.addr) bpflg = 0x100;
321: writeMem(stepPt.addr, &stepPt.code, n, 2);
322: if (stepPt.pc > 0) {
323:
324: writeMem(stepPt.pc, &stepPt.inst, 4, 2);
325:
326: pc = getRegister(stepPt.reg);
327: setRegister(stepPt.reg, stepPt.regval);
328: }
329:
330: if (bpflg != 0) setCurPCX(pc);
331: }
332: }
333:
334:
335: if (! (traceMode || stepFlg)) {
336:
337:
338: for (p = brkPt; p <= &brkPt[MAX_BRKPT]; p++) {
339: if (p->addr == 0) continue;
340:
341: if (p->atr & BA_O) {
342: if (vec == EIT_DDEBUG)
343: bpflg = (p - brkPt) | 0x10;
344: } else if (p->atr & BA_I) {
345: if (pc == p->addr)
346: bpflg = (p - brkPt) | 0x10;
347: } else {
348: readMem(p->addr, &code, n = p->sz, 2);
349: if (memcmp(&code, &sbpCode.b[n], n) == 0) {
350: if (pc == p->addr)
351: bpflg = (p - brkPt) | 0x10;
352: writeMem(p->addr, &p->code, n, 2);
353: p->atr |= BA_SET;
354: } else {
355: p->atr &= ~BA_SET;
356: }
357:
358: if (p->atr & BA_TMP)
359: memset(p, 0, sizeof(BRKPT));
360: }
361: }
362: }
363: return bpflg;
364: }
365: 366: 367:
368: LOCAL void setStep(UW pc, W mode)
369: {
370: W n;
371: UW cpsr, inst;
372:
373:
374: cpsr = getCurCPSR();
375:
376:
377: n = getStepAddr(pc, cpsr, (mode == 2) ? 1 : 0, &stepPt.addr, &inst);
378:
379: if (n >= 0x10) {
380:
381: readMem(stepPt.pc = pc, &stepPt.inst, 4, 2);
382: writeMem(pc, &inst, 4, 2);
383:
384: stepPt.reg = (n >> 4) & 0x0F;
385: stepPt.regval = getRegister(stepPt.reg);
386:
387: setRegister(stepPt.reg, pc + ((cpsr & PSR_T) ? 4 : 8));
388: }
389:
390: stepPt.sz = (n &= 0x0F);
391: readMem(stepPt.addr, &stepPt.code, n, 2);
392: writeMem(stepPt.addr, &sbpCode.b[n], n, 2);
393: }
394: 395: 396:
397: EXPORT void setupBreak(void)
398: {
399: W ibcnt, obcnt;
400: UW bcr, wcr, pc;
401: BRKPT *p;
402:
403: pc = getCurPCX();
404:
405:
406: memset(&stepPt, 0, sizeof(stepPt));
407:
408: if (traceMode) {
409:
410: setStep(pc, traceMode);
411:
412: } else {
413:
414:
415:
416: if (stepFlg == 0) {
417: for (p = brkPt; p <= &brkPt[MAX_BRKPT]; p++) {
418: if (p->addr == pc && (p->atr & BA_PRE)) {
419: setStep(pc, 0);
420: stepFlg = 1;
421: return;
422: }
423: }
424: }
425:
426: ibcnt = obcnt = 0;
427:
428:
429:
430:
431:
432:
433:
434:
435: for (p = brkPt; p <= &brkPt[MAX_BRKPT]; p++) {
436: if (p->addr == 0) continue;
437:
438: if (p->atr & BA_O) {
439: if (!EnableCP14()) continue;
440: wcr = getWCR(obcnt);
441: wcr &= ~0x001FC1FF;
442: wcr |= ((p->atr & (BA_RW)) >> 9) << 3;
443: switch (p->atr >> 24) {
444: case 2: wcr |= 0x060 << (p->addr & 2); break;
445: case 4: wcr |= 0x1e0; break;
446: default: break;
447: }
448: setWVR(obcnt, p->addr & ~3);
449: setWCR(obcnt, wcr | 7);
450: obcnt++;
451: } else if (p->atr & BA_I) {
452: if (!EnableCP14()) continue;
453: bcr = getBCR(ibcnt);
454: bcr &= ~0x007FC1E7;
455: bcr |= (p->addr & 2) ? 0x180 : 0x060;
456: setBVR(ibcnt, p->addr & ~3);
457: setBCR(ibcnt, bcr | 7);
458: ibcnt++;
459: } else if (p->atr & BA_SET) {
460: readMem(p->addr, &p->code, p->sz, 2);
461: writeMem(p->addr, &sbpCode.b[p->sz], p->sz, 2);
462: }
463: }
464:
465:
466:
467: if (ibcnt == 0 && obcnt == 0) DisableCP14();
468: }
469: stepFlg = 0;
470: }
471: 472: 473:
474: EXPORT void stopTrace(void)
475: {
476: traceMode = traceStep = 0;
477: }
478: 479: 480:
481: EXPORT ER goTrace(W trace, UW pc, UW par)
482: {
483: W er;
484:
485:
486: if ((traceMode = trace) == 0) {
487:
488: if (par != 0) {
489: er = setBreak(par, BA_S | BA_PRE | BA_TMP, NULL, 0);
490: if (er < E_OK) return er;
491: }
492: } else {
493: traceStep = par;
494: }
495: setCurPC(pc);
496: return E_OK;
497: }
498: 499: 500: 501: 502:
503: EXPORT W procBreak(W bpflg, UB **cmd)
504: {
505: B *mes;
506: BRKPT *bp;
507: UW pc, npc, wfar;
508:
509: bp = NULL;
510:
511: if (traceMode) {
512:
513: pc = getCurPC();
514:
515:
516: disAssemble(&pc, &npc, wrkBuf);
517: DSP_F4(08X,pc, S,": ", S,wrkBuf, CH,'\n');
518:
519: if (-- traceStep > 0) return 0;
520: stopTrace();
521:
522: } else {
523:
524: if (stepFlg) return 0;
525:
526: pc = getCurPCX();
527:
528:
529: if ((bpflg & 0xF0) == 0) {
530: DSP_F3(S,"Unknown break at H'", 08X,pc, CH,'\n');
531: *cmd = NULL;
532: return 1;
533: }
534:
535: bp = &brkPt[bpflg & 0xF];
536: switch (bp->atr & (BA_S | BA_I | BA_O | BA_R | BA_W)) {
537: case BA_S: mes = "S"; break;
538: case BA_I: mes = "E"; break;
539: case BA_O|BA_R: mes = "R"; break;
540: case BA_O|BA_W: mes = "W"; break;
541: case BA_O|BA_R|BA_W: mes = "RW"; break;
542: default: mes = "?"; break;
543: }
544:
545: if ((bp->atr & BA_O) && CheckCP14()) {
546:
547:
548: wfar = getWFAR();
549: wfar -= (getCurCPSR() & PSR_T) ? 4 : 8;
550: DSP_F4(S,"Break (", S,mes, S,") at ", 08X,wfar);
551: DSP_F3(S," (R15/PC:", 08X,pc, S,")\n");
552: } else {
553: DSP_F5(S,"Break (", S,mes, S,") at ", 08X,pc, CH,'\n');
554: }
555: }
556:
557:
558: *cmd = (bp && bp->cmd[0] != 0) ? bp->cmd : NULL;
559: return 1;
560: }