|
|
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.