|
|
1.1 ! root 1: #include "process.pub" ! 2: #include "frame.pri" ! 3: #include "symtab.pri" ! 4: #include "symbol.h" ! 5: #include "m68kcore.h" ! 6: #include "asm.pri" ! 7: #include "format.pub" ! 8: #include "bpts.pri" ! 9: #include "master.pri" ! 10: SRCFILE("m68kcore.c") ! 11: ! 12: char *M68kCore::read(long l,char *b,int n) { return readwrite(l,b,n,0); } ! 13: char *M68kCore::write(long l,char *b,int n) { return readwrite(l,b,0,n); } ! 14: char *M68kCore::pokedbl(long l,double d,int n) { return write(l,(char*)&d,n);} ! 15: int M68kCore::REG_AP() { return 0; } ! 16: int M68kCore::REG_FP() { return 14; } ! 17: int M68kCore::REG_SP() { return 15; } ! 18: int M68kCore::REG_PS() { return 16; } ! 19: int M68kCore::REG_PC() { return 17; } ! 20: char *M68kCore::readwrite(long, char*,int,int) { return "readwrite"; } ! 21: int M68kCore::instack(long, long) { return 1; } ! 22: int M68kCore::fpvalid(long) { return 1; } ! 23: Behavs M68kCore::behavetype() { return 0; } ! 24: char *M68kCore::dostep(long, long, int) { return "dostep"; } ! 25: long M68kCore::scratchaddr() { return 0; } ! 26: int M68kCore::nregs() { return 18; } ! 27: long M68kCore::regaddr() { return 0; } ! 28: ! 29: char *M68kCore::poke(long l,long d,int n) ! 30: { ! 31: switch (n) { ! 32: case 1: ! 33: return write(l, 3 + (char*)&d,n); ! 34: case 2: ! 35: return write(l, 2 + (char*)&d,n); ! 36: case 4: ! 37: return write(l,(char*)&d,n); ! 38: default: ! 39: return "M68kCore poke error"; ! 40: } ! 41: } ! 42: ! 43: char *M68kCore::liftbpt(Trap *t) ! 44: { ! 45: if( behavs() == ERRORED ) return 0; ! 46: return poke(t->stmt->range.lo, t->saved, 2); ! 47: } ! 48: ! 49: #define REGBIT(r) (1 << r) ! 50: long M68kCore::saved(Frame *f, int r, int) /* ignore size */ ! 51: { ! 52: if( r > 15 ) ! 53: return 0; ! 54: if( !(f->regsave & REGBIT(r)) ) ! 55: return 0; ! 56: long loc = f->regbase; ! 57: while( --r >= 0 ) ! 58: if( f->regsave & REGBIT(r) ) loc += 4; ! 59: return loc; ! 60: } ! 61: ! 62: Asm *M68kCore::newAsm() { return new M68kAsm(this); } ! 63: ! 64: char *M68kCore::regname(int r) ! 65: { ! 66: static char *regnames[] = { "d0", "d1", "d2", "d3", "d4", "d5", ! 67: "d6", "d7", "a0", "a1", "a2", "a3", ! 68: "a4", "a5", "fp", "sp", "ps", "pc", ! 69: "usp", "isp", "vbr", "sfc", "dfc", ! 70: "msp", "cacr", "caar" }; ! 71: if (r < nregs()) ! 72: return regnames[r]; ! 73: else ! 74: return 0; ! 75: } ! 76: ! 77: long M68kCore::regloc(int r, int sz) ! 78: { ! 79: if (r >= 0 && r < nregs()) { ! 80: long ret = 4 * r + regaddr(); ! 81: if (sz && sz < 4) ! 82: ret += 4 - sz; ! 83: return ret; ! 84: } ! 85: return 0; ! 86: } ! 87: ! 88: ! 89: #define CYCLE 4 ! 90: Cslfd *M68kCore::peek(long loc, Cslfd *fail) ! 91: { ! 92: static i; ! 93: static Cslfd *c; ! 94: UCslfd u; ! 95: ! 96: if( read(loc, (char*)&u, 8) ) ! 97: return Core::peek(loc, fail); ! 98: if( !c ) c = new Cslfd[CYCLE]; ! 99: Cslfd *p = c+(i++,i%=CYCLE); ! 100: p->chr = u.chr; ! 101: p->sht = u.sht; ! 102: p->lng = u.lng; ! 103: p->flterr = 0; ! 104: p->flt = u.flt; ! 105: p->dbl = u.dbl; ! 106: return p; ! 107: } ! 108: ! 109: char *M68kCore::peekstring(long loc, char *fail) ! 110: { ! 111: static char buf[256]; ! 112: char *error = read(loc, buf, 250); ! 113: if( error ) ! 114: return fail ? fail : strcpy(buf,error); ! 115: return buf; ! 116: } ! 117: ! 118: CallStk *M68kCore::callstack() // do we have to peek everything twice? ! 119: { ! 120: trace( "%d.callstack()", this ); OK(0); ! 121: long size; ! 122: long _fp = fp(); ! 123: if( !fpvalid(_fp)) ! 124: return (CallStk *)0; ! 125: for( size = 1; size<1000; ++size ){ ! 126: long __fp = peek(_fp)->lng; ! 127: if( !instack(__fp, _fp) ) ! 128: break; ! 129: _fp = __fp; ! 130: } ! 131: CallStk *c = new CallStk(size, this); ! 132: _fp = fp(); ! 133: long _pc = pc(); ! 134: for( long i = 0; i < size; ++i ){ ! 135: c->fpf[i].fp = _fp; ! 136: c->fpf[i].func = (Func*) _symtab->loctosym(U_FUNC, _pc); ! 137: _pc = peek(_fp+4)->lng; ! 138: _fp = peek(_fp)->lng; ! 139: } ! 140: return c; ! 141: } ! 142: ! 143: const short LINKA6=0x4E56, ADDLSP=0xDFFC, MOVEMLSP=0x48D7; ! 144: Frame M68kCore::frameabove(long _fp) ! 145: { ! 146: Frame f(this); ! 147: if( _fp ){ ! 148: f.pc = peek(_fp+4)->lng; ! 149: f.fp = peek(_fp)->lng; ! 150: } else { ! 151: f.pc = pc(); ! 152: f.fp = fp(); ! 153: } ! 154: f.ap = f.fp; ! 155: int callpc = peek(f.fp+4)->lng; ! 156: int inst = peek(callpc)->sht; ! 157: f.regbase = f.fp; ! 158: Func *funcp = (Func*)_symtab->loctosym(U_FUNC, f.pc); ! 159: if (funcp) { ! 160: int faddr = funcp->range.lo; ! 161: if (peek(faddr)->sht == LINKA6) { ! 162: f.regbase += peek(faddr+2)->sht; ! 163: faddr += 4; ! 164: } ! 165: if (peek(faddr)->sht == ADDLSP) { ! 166: f.regbase += peek(faddr+2)->lng; ! 167: faddr += 6; ! 168: } ! 169: if (peek(faddr)->sht == MOVEMLSP) ! 170: f.regsave = peek(faddr+2)->sht; ! 171: } ! 172: return f; ! 173: } ! 174: ! 175: const short M68K_TRAP0=0x4E40, M68K_RTS = 0x4E75, M68K_UNLNKA6 = 0x4E5E; ! 176: char *M68kCore::popcallstack() ! 177: { ! 178: long regaddr, savepc; ! 179: char *error = 0; ! 180: int i; ! 181: short saveinst; ! 182: Cslfd *c; ! 183: ! 184: if( behavetype() == ACTIVE ) ! 185: return "pop callstack: process not stopped"; ! 186: savepc = pc(); ! 187: if( peek(savepc-2)->sht == M68K_TRAP0 ) ! 188: return "pop callstack: process in system call"; ! 189: c = peek(savepc, 0); ! 190: if( !c ) return "cannot pop callstack"; ! 191: saveinst = c->sht; ! 192: // Must be careful if we are in the middle of the call sequence ! 193: switch (saveinst) { ! 194: case M68K_RTS: ! 195: return step(); ! 196: case LINKA6: ! 197: goto rts; ! 198: case MOVEMLSP: ! 199: goto unlink; ! 200: } ! 201: // Sometimes the space is added after the link ! 202: if( peek(savepc-2)->sht == LINKA6 ) ! 203: goto rts; ! 204: // Restore the registers, except the frame pointer and sp ! 205: { // This is here because C++ bitches about gotos if it isn't ! 206: Frame f = frameabove(0); ! 207: for (i = 0; i < 14; i++) ! 208: if (regaddr = saved(&f, i, 4)) ! 209: regpoke(i, peek(regaddr)->lng); ! 210: } ! 211: // Pop the frame ! 212: unlink: if( !error ) error = poke(savepc, M68K_UNLNKA6, 2); ! 213: if( !error ) error = step(); ! 214: if( !error ) regpoke(REG_PC(), savepc); ! 215: // Return from the subroutine ! 216: rts: if( !error ) error = poke(savepc, M68K_RTS, 2); ! 217: if( !error ) error = step(); ! 218: // Restore the instruction ! 219: poke(savepc, saveinst, 2); ! 220: return error; ! 221: } ! 222: ! 223: char *M68kCore::step(long lo, long hi) ! 224: { ! 225: return dostep(lo,hi,1); ! 226: } ! 227: ! 228: const short M68K_BSR = 0x6100, M68K_JSR = 0x4e80; ! 229: const short M68K_BSR_MSK = 0xff00, M68K_JSR_MSK = 0xffc0; ! 230: char *M68kCore::stepoverM68KJSB() ! 231: { ! 232: char *error = 0; ! 233: static Trap *t; ! 234: short inst; ! 235: long fp0, offset; ! 236: ! 237: if(!t) ! 238: t = new Trap(new Stmt(0,0,0),0); ! 239: inst = peek(pc())->sht; ! 240: /* ! 241: * Determine where to put the breakpoint depending on the ! 242: * addressing mode of the instruction. ! 243: */ ! 244: if ((inst & M68K_BSR_MSK) == M68K_BSR) { ! 245: inst &= 0xff; ! 246: if (inst == 0) ! 247: offset = 4; ! 248: else if (inst == 0xff) ! 249: offset = 6; ! 250: else ! 251: offset = 2; ! 252: } else { /* Its a JSR */ ! 253: short reg, mode; ! 254: reg = inst & 07; ! 255: mode = (inst >> 3) & 0x7; ! 256: if (mode == 7) { ! 257: if (reg == 1) ! 258: offset = 6; ! 259: else if (reg == 0 || reg == 2) ! 260: offset = 4; ! 261: else ! 262: goto indexed; ! 263: } else if (mode == 2) ! 264: offset = 2; ! 265: else if (mode == 5) ! 266: offset = 4; ! 267: else { ! 268: indexed: ! 269: inst = peek(pc()+2)->sht; ! 270: offset = 4; ! 271: /* Full format extension */ ! 272: if (inst & 0x0100) { ! 273: /* Base Displacement */ ! 274: if (inst & 0x0020) { ! 275: if (inst & 0x0010) ! 276: offset += 4; ! 277: else ! 278: offset += 2; ! 279: } ! 280: /* Outer Displacement */ ! 281: if (inst & 0x0002) { ! 282: if (inst & 0x0001) ! 283: offset += 4; ! 284: else ! 285: offset += 2; ! 286: } ! 287: } ! 288: } ! 289: ! 290: } ! 291: t->stmt->range.lo = pc()+offset; ! 292: fp0 = fp(); ! 293: if(error = laybpt(t)) ! 294: return error; ! 295: for(;;) { ! 296: error = dostep(0,0,0); ! 297: if (error || fp() >= fp0) ! 298: break; ! 299: if( error = liftbpt(t) ) return error; ! 300: if( error = dostep(0,0,1) ) return error; ! 301: if( error = laybpt(t) ) return error; ! 302: } ! 303: if( !error ) ! 304: error = liftbpt(t); ! 305: else ! 306: liftbpt(t); ! 307: return error; ! 308: } ! 309: ! 310: int M68kCore::isM68KJSB(int inst) ! 311: { ! 312: return (inst & M68K_BSR_MSK) == M68K_BSR || ! 313: (inst & M68K_JSR_MSK) == M68K_JSR; ! 314: } ! 315: ! 316: char *M68kCore::stepprolog() ! 317: { ! 318: Func *f = (Func*)_symtab->loctosym(U_FUNC, pc()); ! 319: if (f) { ! 320: // Only step again if we are in the function prolog ! 321: Stmt *s = f->stmt(pc()); ! 322: if (s && s->range.lo == f->range.lo) ! 323: process()->stmtstep(1); ! 324: } ! 325: return 0; ! 326: } ! 327: ! 328: char *M68kCore::docall(long addr, int numarg) ! 329: { ! 330: const int CALL_SIZE=12, JSR=0x4eb9, ADDSP=0xdffc; ! 331: char save[CALL_SIZE], *error; ! 332: int i; ! 333: ! 334: if( behavetype() == ACTIVE ) ! 335: return "process not stopped"; ! 336: if( !online() ) ! 337: return "cannot restart dump"; ! 338: int callstart = scratchaddr(); ! 339: for( i = 0; i < CALL_SIZE; ++i ) ! 340: save[i] = peek(callstart+i)->chr; ! 341: if( ( error = poke(callstart+0, JSR, 2) ) ! 342: || ( error = poke(callstart+2, addr, 4) ) ! 343: || ( error = poke(callstart+6, ADDSP, 2) ) ! 344: || ( error = poke(callstart+8, numarg * 4, 4) ) ) ! 345: return error; ! 346: if( ( error = regpoke(REG_PC(), callstart) ) ! 347: || ( error = step( callstart, callstart+CALL_SIZE) ) ) ! 348: return error; ! 349: for( i = 0; i < CALL_SIZE; ++i ) ! 350: if( error = poke(callstart+i, save[i], 1 ) ) ! 351: return error; ! 352: return 0; ! 353: } ! 354: ! 355: long M68kCore::apforcall(int argbytes) ! 356: { ! 357: regpoke(REG_SP(), sp() - argbytes); ! 358: return sp() - 8; ! 359: } ! 360: ! 361: long M68kCore::returnregloc() ! 362: { ! 363: return regloc(0); ! 364: } ! 365: ! 366: Context* M68kCore::newContext() ! 367: { ! 368: M68kContext *cc = new M68kContext; ! 369: cc->error = 0; ! 370: cc->core = this; ! 371: if( behavetype() == ACTIVE ) ! 372: cc->error = "context save: process not stopped"; ! 373: if( !cc->error ) ! 374: cc->error = read(regaddr(),(char*)cc->regs,sizeof(cc->regs)); ! 375: return cc; ! 376: } ! 377: ! 378: void M68kContext::restore() ! 379: { ! 380: error = core->write(core->regaddr(), (char*)regs, sizeof(regs)); ! 381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.