📄 dis.c
字号:
perror("fseek"); jumpfree(); } flags = 0; if (insts[offset].size) { if (stored) { flush(stored, consts, 0, 1); stored = 0; } pc = ppc = initialpc + offset; leninstbuf = 0; validinst(); } else { size_t i; if (stored == 0) pc = ppc = initialpc + offset; for (i = 0; i < WORDSIZE; i++) if (fread(consts + stored, 1, 1, infp) == 1) if (++stored >= sizeof consts) { stored = flush(stored, consts, 0, 0); memmove(consts, consts + sizeof consts - stored, stored); } } } if (stored) flush(stored, consts, 0, 1); fflush(NULL);}/* * Make the first pass over the input. * Gather references to other addresses. */voidpass1(void){ m68kaddr offset; pass = FIRSTPASS; for (curoffset = offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) { if (curoffset != offset && fseek(infp, curoffset = offset, SEEK_SET) == -1) { perror("fseek"); jumpfree(); } flags = 0; pc = ppc = offset + initialpc; leninstbuf = 0; if (validinst()) { /* * It's a potential instruction. */ insts[offset].size = curoffset - offset; insts[offset].flags = flags; if (flags & 3) { m68kaddr *reqd; if ((reqd = malloc((flags & 3) * sizeof(*reqd))) == NULL) { perror("malloc"); jumpfree(); } switch (flags & 3) { case 3: reqd[2] = required[2]; case 2: reqd[1] = required[1]; case 1: reqd[0] = required[0]; } insts[offset].required = reqd; } else insts[offset].required = NULL;#ifdef DEBUG if (debug & INITIAL) { int i; fprintf(outfp, "Writing offset = %lx, size = %d, flags = %d", (long)offset, insts[offset].size, insts[offset].flags); for (i = 0; i < (insts[offset].flags & 3); i++) fprintf(outfp, ", reqd = %lx", (long)insts[offset].required[i]); fprintf(outfp, "\n"); }#endif } else {#ifndef NOBAD bad[offset] = offset + initialpc;#endif#ifdef DEBUG if (debug & DELETIONS) fprintf(outfp, "0. Deleting offset %lx\n", (long)offset);#endif } }#if !defined(NOBAD) || defined(DEBUG) for (offset = maxoffset + (odd ? 1 : WORDSIZE); offset <= maxoffset + longestinstsize; offset += (odd ? 1 : WORDSIZE)) {#ifndef NOBAD if (offset <= maxoffset) bad[offset] = offset + initialpc;#endif#ifdef DEBUG if (debug & DELETIONS) fprintf(outfp, "0. Deleting offset %lx\n", (long)offset);#endif }#endif}/* * Make a pass over the instruction database, checking for consistency. */voidfindbadrefs(void){ long offset; /* must be signed */ long offset2; /* must be signed */ int i; size_t size; int changes; int try = 0;#if 0 int totalchanges = 0;#endif#ifdef DEBUG if (debug & TRY) { printall(); fprintf(outfp, "\n\n\n"); }#endif /* * Instructions that don't set PC * must be followed by a valid instruction. */ do { changes = 0; try++; for (offset = maxoffset + longestinstsize; offset >= 0; offset -= (odd ? 1 : WORDSIZE)) { /* * Back up to a possible instruction. * We do this to jump over a large data section. */ for (offset2 = offset; offset2 >= 0 && insts[offset2].size == 0; offset2 -= (odd ? 1 : WORDSIZE)) ; if (offset2 < 0) break; if (offset2 + longestinstsize < offset) offset = offset2 + longestinstsize; if (!linkfallthrough && (insts[offset].flags & ISLINK) || !FETCH(offset, -1)) { /* * We've found an invalid instruction. * See if any instructions advance PC here * based on the size of the instruction * and its operands. */ for (size = odd ? 1 : WORDSIZE; size <= longestinstsize && size <= offset; size += (odd ? 1 : WORDSIZE)) if (FETCH(offset - size, size) && !JUMP(offset - size)) {#ifndef NOBAD if (!linkfallthrough && (insts[offset].flags & ISLINK)) bad[offset - size] = offset + initialpc; else bad[offset - size] = bad[offset];#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "1. Deleting offset %lx, size %d, flags = %d\n", (long)(offset - size), size, insts[offset - size].flags);#endif DELETE(offset - size); changes++; } } } /* * See if any instructions require * an invalid instruction to be valid. */ for (offset2 = 0; offset2 <= maxoffset; offset2 += (odd ? 1 : WORDSIZE)) { if (insts[offset2].size == 0) continue; for (i = 0; i < NREQD(offset2); i++) if (insts[offset2].required[i] >= initialpc && insts[offset2].required[i] <= initialpc + maxoffset && !FETCH(insts[offset2].required[i] - initialpc, -1)) {#ifndef NOBAD bad[offset2] = bad[insts[offset2].required[i] - initialpc];#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "2. Deleting offset %lx, size %d because %lx is not valid\n",(long)offset2, insts[offset2].size, (long)insts[offset2].required[i]);#endif DELETE(offset2); changes++; break; } }#ifdef DEBUG if (debug & TRY) { fprintf(outfp, "TRY %d ###############################\n", try); printall(); fprintf(outfp, "\n\n\n"); }#endif#if 0 totalchanges += changes;#endif } while (changes);#if 0 printf("Tries = %d\n", (int)try); printf("Changes = %d\n", (int)totalchanges);#endif#ifdef DEBUG if (debug & LASTTRY) { fprintf(outfp, "TRY %d ###############################\n", try - 1); printall(); fprintf(outfp, "\n\n\n"); }#endif}struct queue { m68kaddr address; struct queue *next;};/* * The ``writeq'' and ``readq'' functions * maintain a queue of addresses for ``makegood''. */static struct queue head = { 0, NULL };/* * Add to the queue. */static voidwriteq(m68kaddr address){ struct queue *tail; struct queue *newq; if ((newq = malloc(sizeof(*newq))) == NULL) { perror("malloc"); jumpfree(); } newq->address = address;#ifdef DEBUG if (debug & MAKEGOOD) fprintf(outfp, "Wrote offset = %lx\n", (long)address);#endif newq->next = NULL; for (tail = &head; tail->next; tail = tail->next) ; tail->next = newq;}/* * Read (and delete) from the queue. */static struct queue *readq(void){ struct queue *result; if (head.next) { result = head.next; head.next = head.next->next;#ifdef DEBUG if (debug & MAKEGOOD) fprintf(outfp, "Read offset = %lx\n", (long)result->address);#endif } else result = NULL; return result;}/* * Mark ``offset'' as an instruction to be included in the final output. * Recursively mark as good all instructions that reference it. * Delete instructions that contradict those marked good. * Return the number off offsets deleted. */static unsignedmakegood(m68kaddr offset){ size_t size; struct queue *qptr = NULL; m68kaddr origoffset = offset; unsigned deletions = 0; if (insts[offset].flags & ISGOOD) return deletions;#ifdef DEBUG if (debug & MAKEGOOD) fprintf(outfp, "makegood(%lx)\n", (long)offset);#endif do { if (qptr) { offset = qptr->address; free(qptr); }#ifdef DEBUG if (debug & MAKEGOOD) fprintf(outfp, "Going with offset = %lx\n", (long)offset);#endif while (1) {#ifdef DEBUG if (debug & MAKEGOOD) fprintf(outfp, "Offset = %lx\n", (long)offset);#endif if (insts[offset].size == 0 || insts[offset].flags & ISGOOD) break; /* * We have a ``good'' instruction. * Instructions that overlap it should be deleted. */ for (size = odd ? 1 : WORDSIZE; size < longestinstsize && size + maxoffset >= offset && size <= offset; size += (odd ? 1 : WORDSIZE)) if (insts[offset - size].size > size) {#ifndef NOBAD bad[offset - size] = origoffset + initialpc;#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "3. Deleting offset %lx, size %d, flags = %d because of %lx\n", (long)(offset - size), insts[offset - size].size, insts[offset - size].flags, (long)offset);#endif DELETE(offset - size); deletions++; } for (size = odd ? 1 : WORDSIZE; size < insts[offset].size && maxoffset >= offset + size; size += (odd ? 1 : WORDSIZE)) if (insts[offset + size].size) {#ifndef NOBAD bad[offset + size] = origoffset + initialpc;#endif#ifdef DEBUG if (debug & DELETIONS)fprintf(outfp, "4. Deleting offset %lx, size %d, flags = %d because of %lx\n", (long)(offset + size), insts[offset + size].size, insts[offset + size].flags, (long)offset);#endif DELETE(offset + size); deletions++; } insts[offset].flags |= ISGOOD;#ifndef NOBAD good[offset] = origoffset + initialpc;#endif if ((insts[offset].flags & ISBRA) || ((insts[offset].flags & ISJMP) && insts[offset].flags & 3)) { if (insts[offset].required[0] >= initialpc && insts[offset].required[0] <= initialpc + maxoffset) offset = insts[offset].required[0] - initialpc; else break; } else if ((insts[offset].flags & (ISBSR | ISJSR | ISBRA | ISBRcc | ISDBcc | ISJMP)) && (insts[offset].flags & 3) && insts[offset].required[0] >= initialpc && insts[offset].required[0] <= initialpc + maxoffset) { writeq(insts[offset].required[0] - initialpc); offset += insts[offset].size; } else if (insts[offset].flags & (ISRTS | ISJMP)) break; else offset += insts[offset].size; } } while (qptr = readq()); return deletions;}/* * Determine the number of remaining instances * of still-valid instructions overlapping each other. */static longoverlaps(int list){ long num = 0; long offset; size_t size; for (offset = 0; offset <= maxoffset; offset += (odd ? 1 : WORDSIZE)) { if (insts[offset].size == 0) continue; for (size = odd ? 1 : WORDSIZE; size < longestinstsize && size <= offset; size += (odd ? 1 : WORDSIZE)) if (insts[offset - size].size > size) { num++; if (list) fprintf(stderr, "%s: Overlap at %lx\n", sfile, offset); } } return num;}/* * Starting from ``offset'', return the next highest offset * containing an instruction marked good (or -1). */static longnextgood(m68kaddr offset){ long next; for (next = offset + (odd ? 1 : WORDSIZE); next <= maxoffset && (insts[next].size == 0 || (insts[next].flags & ISGOOD) == 0); next += (odd ? 1 : WORDSIZE)) ; return (next > maxoffset) ? -1 : next;}/* * Return whether program flow reaches address ``target'' * starting from address ``prevonly''. */static intreach(m68kaddr prevonly, m68kaddr target){ m68kaddr offset; for (offset = prevonly; insts[offset].size && offset < target; offset += insts[offset].size) ; return offset == target;}/* * Fix the overlap situation. * Do this by minimizing the amount of data (constants) in the input. */static unsignedfixoverlaps(void){ m68kaddr offset; m68kaddr goodone = nextgood(0); unsigned deletions = 0; for (offset = 0; offset <= maxoffset; ) { if (insts[offset].size == 0) { if (odd) offset++; else offset += WORDSIZE; continue; } if (insts[offset].flags & ISGOOD) { offset += insts[offset].size; continue; } if (/*goodone >= 0 &&*/ goodone <= offset) goodone = nextgood(offset); if (reach(offset, goodone)) deletions += makegood(offset); else if (odd) offset++; else offset += WORDSIZE; } return deletions;}static intaddrcmp(const void *p1, const void *p2){ m68kaddr a1 = *(m68kaddr *)p1; m68kaddr a2 = *(m68kaddr *)p2; if (a1 < a2) return -1; else if (a1 > a2) return 1; else return 0;}/* * Return whether a ``math'' FPU instruction * has the word at ``offset'' as an extension word. */static intfpuoverlap(m68kaddr offset){ size_t size; if (!FPU(chip) || (insts[offset].flags & (ISBSR | ISBRA | ISBRcc)) == 0) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -