/* This file is in the public domain. */ #include #include #include #include #include #ifndef M_LOG10_2 #if defined(M_LOG10E) && defined(M_LN2) #define M_LOG10_2 (M_LOG10E * M_LN2) #else #define M_LOG10_2 0.301029995663981195214158462137659761463 #endif #endif #include "sortsearch.h" #include "fnprintf.h" #include "machine.h" #include "machine-m68k.h" extern INSTR Machine_m68k_instrs[]; extern int Machine_m68k_ninstrs; extern INSTR *Machine_m68k_cptbl[]; extern int Machine_m68k_ncptbl[]; static unsigned short int iv[65536]; #define IV_NIL 65535 #define IV_NONE 65534 #define IV_HARD 65533 #define IV_COPROC 65532 #define IV_MBYTE_TOP 65531 #define IV_MBYTE_BASE (IV_MBYTE_TOP-MAXWORDS) #define IV_ISMBYTE(x) (((unsigned short int)((x)-(IV_MBYTE_BASE+2)))<=(MAXWORDS-2)) #define IV_MBYTE(nb) (IV_MBYTE_BASE+(nb)) #define IV_MBYTE_NB(n) ((n)-IV_MBYTE_BASE) enum fmtcode { F_NONE = 0, F_BINARY, F_DECIMAL, F_UNSIGNED, F_HEX, F_QUICK, F_SRBITS, F_GUESS, F_PERSIZE, F_MOVEM_A7_TO_D0, F_MOVEM_D0_TO_A7, F_FMOVEM_FP0_TO_FP7, F_FMOVEM_FP7_TO_FP0 } ; #define SIGNEDFMT(f) (((f)==F_DECIMAL)||((f)==F_GUESS)) typedef enum fmtcode FMTCODE; static const char *aregs[8] = { "a0","a1","a2","a3","a4","a5","fp","sp" }; static const char *dregs[8] = { "d0","d1","d2","d3","d4","d5","d6","d7" }; static const char **regvecs[2] = { &dregs[0], &aregs[0] }; #define unsignedbits(val,at,n)\ ((((unsigned long int)(val)) >> (at)) & ~((~0UL) << (n))) static char *dis_buf = 0; static int dis_have = 0; static int dis_len = 0; static long int signedbits(unsigned long int val, unsigned int at, unsigned int n) { unsigned long int l; l = unsignedbits(val,at,n); if (l & (1 << (n-1))) l |= (~0UL) << n; return(l); } static int hexcval(char c) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return(c-'0'); break; case 'a': case 'A': return(10); break; case 'b': case 'B': return(11); break; case 'c': case 'C': return(12); break; case 'd': case 'D': return(13); break; case 'e': case 'E': return(14); break; case 'f': case 'F': return(15); break; } return(-1); } static void (*dis_fn)(char); static int dis_nw; static unsigned short int *dis_opcw; static const char *dis_dp; static int dis_lasts; static ADDR dis_addr; static unsigned char ifss[MAXIFSDEPTH]; #define IFS_TRUE 0 #define IFS_PREFALSE 1 #define IFS_POSTFALSE 2 static unsigned int ifsd; #define TRUECOND (ifss[ifsd]==IFS_TRUE) #define fn dis_fn #define nw dis_nw #define opcw dis_opcw #define dp dis_dp #define lasts dis_lasts #define addr dis_addr static void badfmt(const char *why) { fprintf(stderr,"illegal format: %s\n",why); abort(); } inline static unsigned long int opcbfu(unsigned int o, unsigned int w) { return(unsignedbits(opcw[o/16],o%16,w)); } static long int opcbfs(unsigned int o, unsigned int w) { return(signedbits(opcw[o/16],o%16,w)); } static int getnum(void) { int cv; unsigned int v; const char *p; p = dp; switch (*p) { case '(': v = 0; p ++; for (;*p!=')';p++) { cv = hexcval(*p); if (cv < 0) badfmt("illegal character in number"); v = (v << 4) | cv; } dp = p + 1; return(v); break; } cv = hexcval(*p); if (cv < 0) return(-1); dp = p + 1; return(cv); } static unsigned int getoff(unsigned int w) { int o; o = getnum(); if (o < 0) badfmt("missing/illegal bit offset"); if (o+w > 16*nw) badfmt("bit offset too large"); return(o); } static char getopfmt(void) #define OF_NONE (-1) #define OF_BINT 1 #define OF_WINT 2 #define OF_LINT 3 #define OF_SFLT 4 #define OF_DFLT 5 #define OF_XFLT 6 #define OF_PFLT 7 #define OF__INT(x) (3 > (unsigned int)((x)-1)) #define OF__FLT(x) (4 > (unsigned int)((x)-4)) { char vec[8]; unsigned int w; int v; vec[0] = 'b'; vec[1] = 'w'; vec[2] = 'l'; vec[3] = '?'; w = 2; switch (*dp++) { case 'b': return(OF_BINT); break; case 'w': return(OF_WINT); break; case 'l': return(OF_LINT); break; case 's': return(OF_SFLT); break; case 'd': return(OF_DFLT); break; case 'x': return(OF_XFLT); break; case 'p': return(OF_PFLT); break; case 'S': if ((lasts < 0) && TRUECOND) badfmt("size code S used without preceding %s/%S"); return(lasts); break; case 'v': if (! (dp[0] && dp[1] && dp[2] && dp[3] && dp[4])) badfmt("not enough characters after size v"); vec[0] = dp[0]; vec[1] = dp[1]; vec[2] = dp[2]; vec[3] = dp[3]; dp += 4; break; case 'V': if (! (dp[0] && dp[1] && dp[2])) badfmt("not enough characters after size V"); vec[0] = dp[0]; vec[1] = dp[1]; dp += 2; w = 1; break; case 'f': bcopy("lsxpwdb?",&vec[0],8); w = 3; break; default: dp --; break; } v = opcbfu(getoff(w),w); switch (vec[v]) { case 'b': return(OF_BINT); break; case 'w': return(OF_WINT); break; case 'l': return(OF_LINT); break; case 's': return(OF_SFLT); break; case 'd': return(OF_DFLT); break; case 'x': return(OF_XFLT); break; case 'p': return(OF_PFLT); break; } return(OF_NONE); } static int opf_size(int opfmt) { switch (opfmt) { case OF_BINT: return(1); break; case OF_WINT: return(2); break; case OF_LINT: return(4); break; case OF_SFLT: return(4); break; case OF_DFLT: return(8); break; case OF_XFLT: return(12); break; case OF_PFLT: return(12); break; } return(-1); } static char opf_char(int opfmt) { switch (opfmt) { case OF_BINT: return('b'); break; case OF_WINT: return('w'); break; case OF_LINT: return('l'); break; case OF_SFLT: return('s'); break; case OF_DFLT: return('d'); break; case OF_XFLT: return('x'); break; case OF_PFLT: return('p'); break; } return('?'); } static FMTCODE getfmtcode(void) { switch (*dp++) { case 'b': return(F_BINARY); break; case 'd': return(F_DECIMAL); break; case 'u': return(F_UNSIGNED); break; case 'x': return(F_HEX); break; case 'q': return(F_QUICK); break; case 's': return(F_SRBITS); break; case 'g': return(F_GUESS); break; case 'm': switch (*dp++) { case '+': return(F_MOVEM_A7_TO_D0); break; case '-': return(F_MOVEM_D0_TO_A7); break; } dp --; break; case 'M': switch (*dp++) { case '+': return(F_FMOVEM_FP7_TO_FP0); break; case '-': return(F_FMOVEM_FP0_TO_FP7); break; } dp --; break; } dp --; badfmt("bad print-format code"); return(F_NONE); } static unsigned int bitcount(unsigned long int v) { v = (v & 0x55555555) + ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); v = (v & 0x0f0f0f0f) + ((v >> 4) & 0x0f0f0f0f); v = (v & 0x00ff00ff) + ((v >> 8) & 0x00ff00ff); return((v&0x0000ffff)+((v>>16)&0x0000ffff)); } static void print_sym_for_addr(ADDR a) { SYMBOL *s; if ((a >= corebase) && (a <= coreend)) { s = symbol_for_addr(a); if (s) fnprintf(fn," <%s>",s->name); } maybe_print_stringptr(fn,a); } /* * Try to guess what the most useful base for printing a value is. * * - -31 through 31 are printed as ordinary decimal * - If the number has only one or two bits set, use hex * - If the number's complement has only one or two bits set, * print it as ~0x%lx * - If the number or its negative is within 3 of a power of 10, * use decimal * - If the number or its negative is within 3 of a power of 2, * use hex * - If the set bits are all in the most-significant 1/4 of the number, * or (a) no more than 1/3 of the number's bits are set and (b) * at least half the digits are 0 when in hex, use hex * - If the number's complement satisfies the previous condition, * use ~0x%lx * - Else use decimal if absolute value is < 64k, hex otherwise. */ static void print_heuristic_base(long int v, int sz) { unsigned long int ut; unsigned int setbits; unsigned int setbitsc; static unsigned long int powers10[] = { 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; int i; unsigned int power2; unsigned int lg; unsigned int hex0; unsigned long int hexmask; if (fn == 0) return; /* save effort */ if ((v > -32) && (v < 32)) { fnprintf(fn,"%ld",v); return; } switch (sz) { case 1: hexmask = 0x000000ff; break; case 2: hexmask = 0x0000ffff; break; case 4: hexmask = 0xffffffff; break; } setbits = bitcount(v); setbitsc = bitcount(~(unsigned long int)v); if (setbits < 3) { fnprintf(fn,"0x%0*lx",sz*2,hexmask&(unsigned long int)v); print_sym_for_addr(v); return; } if (setbitsc < 3) { fnprintf(fn,"~0x%0*lx",sz*2,hexmask&~(unsigned long int)v); return; } for (i=0;i<(sizeof(powers10)/sizeof(powers10[0]));i++) { if ( (( v >= powers10[i]-3) && ( v <= powers10[i]+3)) || ((-v >= powers10[i]-3) && (-v <= powers10[i]+3)) ) { fnprintf(fn,"%ld",v); return; } } for (i=0;i<32;i++) { if ( (( v >= (1UL<= (1UL<>=1) power2 ++; lg = power2; for (;ut;ut>>=1) lg ++; hex0 = 0; for (ut=v;ut;ut>>=4) if ((ut & 0xf) == 0) hex0 ++; if ( ((lg-power2)*3 <= power2) || ((hex0*2 >= (lg-1)/4) && (setbits*3 <= lg)) ) { fnprintf(fn,"0x%0*lx",sz*2,hexmask&(unsigned long int)v); print_sym_for_addr(v); return; } power2 = 0; for (ut=~(unsigned long int)v;!(ut&1);ut>>=1) power2 ++; lg = power2; for (;ut;ut>>=1) lg ++; hex0 = 0; for (ut=~(unsigned long int)v;ut;ut>>=4) if ((ut & 0xf) == 0) hex0 ++; if ( ((lg-power2)*3 <= power2) || ((hex0*2 >= (lg-1)/4) && (setbits*3 <= lg)) ) { fnprintf(fn,"~0x%0*lx",sz*2,hexmask&~(unsigned long int)v); return; } if ((v >= -65536) && (v <= 65536)) { fnprintf(fn,"%ld",v); } else { fnprintf(fn,"0x%0*lx",sz*2,hexmask&(unsigned long int)v); } print_sym_for_addr(v); } static void print_in_fmt(unsigned long int v, FMTCODE fmt, unsigned int w) { switch (fmt) { case F_BINARY: { int i; for (i=w-1;i>=0;i--) { fnprintf(fn,"%c",'0'+(int)((v>>i)&1)); } } break; case F_DECIMAL: fnprintf(fn,"%ld",v); break; case F_UNSIGNED: fnprintf(fn,"%lu",v); break; case F_HEX: if (v == 0) { fnprintf(fn,"0"); } else { fnprintf(fn,"0x%0*lx",(w+3)>>2,v); } break; case F_QUICK: if (v == 0) v = 1UL << w; fnprintf(fn,"%lu",v); break; case F_SRBITS: { const char *s; fnprintf(fn,"0x%0*lx<",w/4,v); s = ""; #define BIT(bit,name) if (v & (1UL<<(bit))) { fnprintf(fn,"%s%s",s,(name)); s = "|"; } BIT(15,"T1"); BIT(14,"T0"); BIT(13,"S"); BIT(12,"M"); fnprintf(fn,"%sPL%lu",s,(v>>8)&7); s = "|"; BIT(4,"X"); BIT(3,"N"); BIT(2,"Z"); BIT(1,"V"); BIT(0,"C"); if (v & 0x08e0) fnprintf(fn,"%s0x%04lx",s,v&0x08e0); #undef BIT fnprintf(fn,">"); } break; case F_GUESS: print_heuristic_base(v,(w+7)>>3); break; case F_MOVEM_A7_TO_D0: { int inc; int i; int i0; int j; const char *s; int vn; inc = 1; j = 0; if (0) { case F_MOVEM_D0_TO_A7: inc = -1; j = 15; } fnprintf(fn,"%04lx<",v); s = ""; for (vn=0;vn<2;vn++) { i0 = -1; for (i=0;i<=8;i++,j+=inc) { if ((i < 8) && (v & (1 << j))) { if (i0 < 0) i0 = i; } else { if (i0 >= 0) { fnprintf(fn,"%s%s",s,regvecs[vn][i0]); if (i > i0+2) { fnprintf(fn,"-%s",regvecs[vn][i-1]); } else if (i == i0+2) { fnprintf(fn,"/%s",regvecs[vn][i-1]); } s = "/"; i0 = -1; } } } j -= inc; } fnprintf(fn,">"); } break; case F_FMOVEM_FP7_TO_FP0: { int inc; int i; int i0; int j; const char *s; inc = 1; j = 0; if (0) { case F_FMOVEM_FP0_TO_FP7: inc = -1; j = 7; } fnprintf(fn,"%02lx<",v); s = ""; i0 = -1; for (i=0;i<=8;i++,j+=inc) { if ((i < 8) && (v & (1 << j))) { if (i0 < 0) i0 = i; } else { if (i0 >= 0) { fnprintf(fn,"%sfp%d",s,i0); if (i > i0+2) { fnprintf(fn,"-fp%d",i-1); } else if (i == i0+2) { fnprintf(fn,"/fp%d",i-1); } s = "/"; i0 = -1; } } } fnprintf(fn,">"); } break; default: abort(); break; } } static void print_flt(void (*fn)(char), int opf, unsigned char *dbuf) { int neg; int exp; int ebias; int emax; int mlen; int mfnib; unsigned char mantissa[9]; static char zero[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int i; int j; int exp10; int exp10f; double mfac; double mant; double p2; bzero(&mantissa[0],9); switch (opf) { case OF_SFLT: neg = (dbuf[0] & 0x80) ? 1 : 0; exp = ((dbuf[0] & 0x7f) << 1) | (dbuf[1] >> 7); ebias = 127; emax = 0xff; bcopy(&dbuf[1],&mantissa[0],3); mantissa[0] |= 0x80; mlen = 3; mfnib = 6; break; case OF_DFLT: neg = (dbuf[0] & 0x80) ? 1 : 0; exp = ((dbuf[0] & 0x7f) << 4) | (dbuf[1] >> 4); ebias = 1023; emax = 0x7ff; for (i=0;i<6;i++) mantissa[i] = (dbuf[i+1] << 3) | (dbuf[i+2] >> 5); mantissa[6] = dbuf[7] << 3; mantissa[0] |= 0x80; mlen = 7; mfnib = 13; break; case OF_XFLT: neg = (dbuf[0] & 0x80) ? 1 : 0; exp = ((dbuf[0] & 0x7f) << 8) | dbuf[1]; ebias = 16383; emax = 0x7fff; bcopy(&dbuf[4],&mantissa[0],8); mlen = 8; mfnib = 16; break; case OF_PFLT: if (((dbuf[0]&0x7f) == 0x7f) && (dbuf[1] == 0xff)) { if (bcmp(&dbuf[4],&zero[0],8)) { fnprintf(fn,"%c%s:",(dbuf[0]&0x80)?'-':'+',(dbuf[4]&0x40)?"NAN":"SNAN"); for (i=0;i<8;i++) fnprintf(fn,"%02X",dbuf[i+4]); } else { fnprintf(fn,"%cINF",(dbuf[0]&0x80)?'-':'+'); } } else if (((dbuf[3]&0x0f) == 0x00) && !bcmp(&dbuf[4],&zero[0],8)) { fnprintf(fn,"%c0e%c0",(dbuf[0]&0x80)?'-':'+',(dbuf[0]&0x40)?'-':'+'); } else { fnprintf(fn,"%c%X.",(dbuf[0]&0x80)?'-':'+',dbuf[3]&0x0f); for (i=0;i<8;i++) fnprintf(fn,"%02X",dbuf[i+4]); fnprintf(fn,"e%c%X%02X",(dbuf[0]&0x40)?'-':'+',dbuf[0]&0x0f,dbuf[1]); } return; break; } if (exp == emax) { if (((mantissa[0] & 0x7f) == 0) && !bcmp(&mantissa[1],&zero[0],7)) { fnprintf(fn,"%cINF",neg?'-':'+'); } else { fnprintf(fn,"%c%s:",neg?'-':'+',(mantissa[0]&0x40)?"NAN":"SNAN"); for (i=0;iexp10 conversion */ if ((exp10f > 0) && (exp10 > exp10f)) exp10 --; else if ((exp10f < 0) && (exp10 < exp10f)) exp10 ++; mfac = pow(10,exp10f-exp10); mant = 0; p2 = 1; for (i=0;i= 10) { mant /= 10; exp10 ++; } { char obuf[64]; sprintf(&obuf[0],"%g",mant); fnprintf(fn,"%c%se%+d",neg?'-':'+',&obuf[0],exp10); fnprintf(fn,"[%d.",mantissa[0]>>7); for (i=0;i>1]<<1)|(mantissa[(i>>1)+1]>>7)):(mantissa[i>>1]>>3))&0x0f); } if (exp > ebias) { fnprintf(fn,"e+%X]",exp-ebias); } else { fnprintf(fn,"e-%X]",ebias-exp); } } } static void print_persize(unsigned char *buf, int sz) { switch (sz) { case OF_BINT: fnprintf(fn,"%ld",signedbits(buf[0],0,8)); break; case OF_WINT: fnprintf(fn,"%ld",signedbits((buf[0]<<8)|buf[1],0,16)); break; case OF_LINT: fnprintf(fn,"%d",(int)((buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3])); break; case OF_SFLT: case OF_DFLT: case OF_XFLT: case OF_PFLT: print_flt(fn,sz,buf); break; } } static int dis_extended_mode(const char *breg, const char *suppbreg) { unsigned short int eword; const char *ireg; const char *ilen; const char *imul; if (addr+2 > coresize) return(1); eword = corefetchu(addr,2); addr += 2; if ( ((eword & 0x0108) == 0x0108) || ((eword & 0x0130) == 0x0100) || ((eword & 0x0147) == 0x0104) || ((eword & 0x0144) == 0x0144) ) { fnprintf(fn,"<%04hx,%s>",eword,breg); } else { ireg = ((eword & 0x8000) ? &aregs[0] : &dregs[0]) [unsignedbits(eword,12,3)]; ilen = (eword & 0x0800) ? "l" : "w"; switch (eword & 0x0600) { case 0x0000: imul = ""; break; case 0x0200: imul = "*2"; break; case 0x0400: imul = "*4"; break; case 0x0600: imul = "*8"; break; } if (eword & 0x0100) { int sz; long int o; if (eword & 0x0080) { fnprintf(fn,"%s",suppbreg); } else { fnprintf(fn,"%s@",breg); } if ((eword & 0x0020) || ((eword & 0x0044) == 0)) { fnprintf(fn,"("); if (eword & 0x0020) { sz = (eword & 0x0010) ? 4 : 2; if (addr+sz > coresize) return(1); o = corefetchs(addr,sz); addr += sz; print_heuristic_base(o,sz); fnprintf(fn,":%c","??w?l"[sz]); if ((eword & 0x0044) == 0) fnprintf(fn,","); } if ((eword & 0x0044) == 0) { fnprintf(fn,"%s:%s%s",ireg,ilen,imul); } fnprintf(fn,")"); } if ((eword & 0x0007) != 0) { fnprintf(fn,"@"); if ((eword & 0x0002) || ((eword & 0x0044) == 0x0004)) { fnprintf(fn,"("); if (eword & 0x0002) { sz = (eword & 0x0001) ? 4 : 2; if (addr+sz > coresize) return(1); o = corefetchs(addr,sz); addr += sz; print_heuristic_base(o,sz); fnprintf(fn,":%c","??w?l"[sz]); if ((eword & 0x0044) == 0x0004) fnprintf(fn,","); } if ((eword & 0x0044) == 0x0004) { fnprintf(fn,"%s:%s%s",ireg,ilen,imul); } fnprintf(fn,")"); } } } else { fnprintf(fn,"%s@(%ld,%s:%s%s)",breg,signedbits(eword,0,8),ireg,ilen,imul); } } return(0); } static int dis_fmt(void (*arg_fn)(char), int arg_nw, unsigned short int *arg_opcw, ADDR *ap, const char *desc) #define DFR_OK 0 /* completed successfully */ #define DFR_OVERRUN 1 /* fell off the edge of core */ #define DFR_FORBIDDEN 2 /* format indicated failure to match */ { int opat; fn = arg_fn; nw = arg_nw; opcw = arg_opcw; dp = desc; addr = *ap; lasts = -1; ifss[0] = IFS_TRUE; ifsd = 0; while (*dp) { if (*dp != '%') { if (TRUECOND) fnprintf(fn,"%c",*dp); dp ++; continue; } dp ++; switch (*dp++) { case 'a': opat = getoff(3); if (TRUECOND) fnprintf(fn,"%s",aregs[opcbfu(opat,3)]); break; case 'd': opat = getoff(3); if (TRUECOND) fnprintf(fn,"%s",dregs[opcbfu(opat,3)]); break; case 'r': opat = getoff(4); if (TRUECOND) fnprintf(fn,"%s",regvecs[opcbfu(opat+3,1)][opcbfu(opat,3)]); break; case 's': { int printit; int sz; printit = 1; if (0) { case 'S': printit = 0; } lasts = -1; sz = getopfmt(); if (TRUECOND) { if (sz < 0) return(DFR_FORBIDDEN); lasts = sz; if (printit) fnprintf(fn,"%c",opf_char(sz)); } } break; case 'g': { int sz; char modecode; unsigned int m; unsigned int r; sz = lasts; modecode = *dp++; m = 3; r = 0; if (0) { case 'G': sz = getopfmt(); modecode = *dp++; m = getoff(3); r = getoff(3); } if (TRUECOND) { if (sz < 0) badfmt("%g used without preceding %s/%S"); m = opcbfu(m,3); r = opcbfu(r,3); switch (m) { case 0: switch (modecode) { case '3': case '7': case '8': case 'b': case 'c': return(DFR_FORBIDDEN); break; case '2': case '4': if (opf_size(sz) > 4) return(DFR_FORBIDDEN); break; } fnprintf(fn,"%s",dregs[r]); break; case 1: switch (modecode) { case '1': case '5': if (sz == OF_BINT) return(DFR_FORBIDDEN); break; default: return(DFR_FORBIDDEN); break; } fnprintf(fn,"%s",aregs[r]); break; case 2: fnprintf(fn,"%s@",aregs[r]); break; case 3: switch (modecode) { case '6': case '7': case '8': case '9': case 'c': return(DFR_FORBIDDEN); break; } fnprintf(fn,"%s@+",aregs[r]); break; case 4: switch (modecode) { case '6': case '7': case '8': case '9': case 'b': return(DFR_FORBIDDEN); break; } fnprintf(fn,"%s@-",aregs[r]); break; case 5: if (addr+2 > coresize) return(DFR_OVERRUN); fnprintf(fn,"%s@(%ld)",aregs[r],corefetchs(addr,2)); addr += 2; break; case 6: if (dis_extended_mode(aregs[r],"")) return(DFR_OVERRUN); break; case 7: switch (r) { case 0: { ADDR a; if (addr+2 > coresize) return(DFR_OVERRUN); a = corefetchs(addr,2); addr += 2; print_symbol_or_hex(fn,a); fnprintf(fn,":w"); } break; case 1: { ADDR a; if (addr+4 > coresize) return(DFR_OVERRUN); a = corefetchs(addr,4); addr += 4; print_symbol_or_hex(fn,a); fnprintf(fn,":l"); } break; case 2: switch (modecode) { case '3': case '4': case '5': case '8': case '9': case 'c': return(DFR_FORBIDDEN); break; } { long int disp; if (addr+2 > coresize) return(DFR_OVERRUN); disp = corefetchs(addr,2); addr += 2; print_symbol_or_hex(fn,corebase+addr+disp-2); } break; case 3: switch (modecode) { case '3': case '4': case '5': case '8': case '9': case 'c': return(DFR_FORBIDDEN); break; } if (dis_extended_mode("pc","zpc")) return(DFR_OVERRUN); break; case 4: switch (modecode) { case '1': case '2': break; default: return(DFR_FORBIDDEN); break; } { long int data; unsigned char fbuf[12]; fnprintf(fn,"#"); switch (sz) { case OF_BINT: if (addr+2 > coresize) return(DFR_OVERRUN); data = signedbits(corefetchu(addr,2),0,8); addr += 2; print_heuristic_base(data,1); break; case OF_WINT: if (addr+2 > coresize) return(DFR_OVERRUN); data = corefetchs(addr,2); addr += 2; print_heuristic_base(data,2); break; case OF_LINT: if (addr+4 > coresize) return(DFR_OVERRUN); data = corefetchs(addr,4); addr += 4; print_heuristic_base(data,4); break; case OF_SFLT: case OF_DFLT: case OF_XFLT: case OF_PFLT: { int i; int n; n = opf_size(sz); if (addr+n > coresize) return(DFR_OVERRUN); for (i=0;i",r); break; } break; } } } break; case 'i': { FMTCODE fmt; int sz; int isz; long int v; fmt = getfmtcode(); sz = getopfmt(); if (TRUECOND) { if (sz < 0) return(DFR_FORBIDDEN); isz = opf_size(sz); if (isz == 1) isz = 2; if (addr+isz > coresize) return(DFR_OVERRUN); if (OF__INT(sz)) { if (SIGNEDFMT(fmt)) { v = corefetchs(addr,isz); addr += isz; if (sz == OF_BINT) v = signedbits(v,0,8); } else { v = corefetchu(addr,isz); addr += isz; if (sz == OF_BINT) v = unsignedbits(v,0,8); } print_in_fmt(v,fmt,opf_size(sz)*8); } else { unsigned char vb[12]; int i; if (fmt != F_PERSIZE) abort(); for (i=0;i",v); break; } } } break; case 'c': { unsigned int flag; #define CF_NO_TF 1 #define CF_NO_SP 2 #define CF_SPACE 4 unsigned int cond; flag = 0; while (1) { switch (*dp++) { case '*': flag |= CF_NO_TF; continue; break; case '!': flag |= CF_NO_SP; continue; break; case 'p': flag |= CF_SPACE; continue; break; } break; } dp --; opat = getoff(4); if (TRUECOND) { cond = opcbfu(opat,4); if (cond < 2) { if (flag & CF_NO_TF) return(DFR_FORBIDDEN); if (flag & CF_SPACE) { fnprintf(fn," "); } else { fnprintf(fn,"%c","tf"[cond]); if (! (flag & CF_NO_SP)) fnprintf(fn," "); } } else { static const char condnames[16*2] = "....hilscccsneeqvcvsplmigeltgtle"; if (! (flag & CF_SPACE)) fnprintf(fn,"%.2s",&condnames[cond*2]); } } } break; case 't': { long int disp; disp = opcbfs(0,8); if (disp == 0) { int siz; siz = 2; if (0) { case 'T': switch (*dp++) { case 'w': siz = 2; break; case 'l': siz = 4; break; default: badfmt("%T with invalid following character"); break; } } if (TRUECOND) { if (addr+siz > coresize) return(DFR_OVERRUN); disp = corefetchs(addr,siz); addr += siz; } } else if (disp == -1) { if (TRUECOND) { if (addr+4 > coresize) return(DFR_OVERRUN); disp = corefetchs(addr,4); addr += 4; } } if (TRUECOND) print_symbol_or_hex(fn,corebase+(*ap)+disp); } break; case 'v': { FMTCODE fmt; int w; fmt = getfmtcode(); opat = getoff(0); w = getnum(); if (TRUECOND) { if (w < 0) badfmt("bad size for %v"); if (opat+w > 16*nw) badfmt("bit offset too large"); if (SIGNEDFMT(fmt)) { fnprintf(fn,"%ld",opcbfs(opat,w)); } else { print_in_fmt(opcbfu(opat,w),fmt,w); } } } break; case 'B': { FMTCODE fmt; unsigned int v; switch (*dp++) { case 'o': fmt = F_UNSIGNED; break; case 'w': fmt = F_QUICK; break; default: badfmt("bad subkey after %B"); break; } opat = getoff(6); if (TRUECOND) { v = opcbfu(opat,6); if (v & 040) { fnprintf(fn,"%s",dregs[v&7]); if (v & 030) fnprintf(fn,"<%x>",v&030); } else { print_in_fmt(v,fmt,5); } } } break; case 'F': { char c; int flg; #define FFLG_BANG 0x01 #define FFLG_PLUS 0x02 unsigned int v; flg = 0; while (1) { c = *dp++; switch (c) { case '!': flg |= FFLG_BANG; continue; break; case '+': flg |= FFLG_PLUS; continue; break; } break; } switch (c) { case 'c': { static const char *fcond[0100] = { "t" , "eq" , "ogt" , "oge" , "olt" , "ole" , "ogl" , "or" , "un" , "ueq" , "ugt" , "uge" , "ult" , "ule" , "ne" , "f" , "sf" , "seq" , "gt" , "ge" , "lt" , "le" , "gl" , "gle" , "ngle", "ngl" , "nle" , "nlt" , "nge" , "ngt" , "sne" , "st" , "?40" , "?41" , "?42" , "?43" , "?44" , "?45" , "?46" , "?47" , "?50" , "?51" , "?52" , "?53" , "?54" , "?55" , "?56" , "?57" , "?60" , "?61" , "?62" , "?63" , "?64" , "?65" , "?66" , "?67" , "?70" , "?71" , "?72" , "?73" , "?74" , "?75" , "?76" , "?77" }; opat = getoff(6); if (TRUECOND) { v = opcbfu(opat,6); if (! (flg & FFLG_PLUS)) fnprintf(fn,"%s",fcond[v]); if (! (flg & FFLG_BANG)) fnprintf(fn,"%*s",4-(int)strlen(fcond[v]),""); } } break; case 'r': { static const char *romnames[0200] = { "pi", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "log10(2)", "e", "log2(e)", "log10(e)", "zero", /* 00-0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10-1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20-2f */ "ln(2)", "ln(10)", "1", "10", "10^2", "10^4", "10^8", "10^16", /* 30-37 */ "10^32", "10^64", "10^128", "10^256", "10^512", "10^1024", "10^2048", "10^4096", /* 38-3f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40-4f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50-5f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60-6f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70-7f */ }; opat = getoff(7); if (TRUECOND) { v = opcbfu(opat,7); fnprintf(fn,"%s",romnames[v]?romnames[v]:"unknown"); } } break; default: badfmt("invalid subcharacter for %F"); break; } #undef FFLG_BANG #undef FFLG_PLUS } break; case 'X': if (TRUECOND) return(DFR_FORBIDDEN); break; case '?': { long int o[2]; char cmp; int oo; int ow; int n; unsigned char newifs; cmp = *dp++; switch (cmp) { case '<': case '=': case '>': break; default: badfmt("improper comparison character after %?"); break; } for (n=0;n<2;n++) { if (*dp == '!') { dp ++; o[n] = getnum(); } else { if (*dp == '+') { dp ++; oo = getoff(0); ow = getnum(); if (oo+ow > 16*nw) badfmt("bit offset too large"); o[n] = opcbfs(oo,ow); } else { oo = getoff(0); ow = getnum(); if (oo+ow > 16*nw) badfmt("bit offset too large"); o[n] = opcbfu(oo,ow); } } } switch (cmp) { case '<': cmp = (o[0] < o[1]); break; case '=': cmp = (o[0] == o[1]); break; case '>': cmp = (o[0] > o[1]); break; } newifs = TRUECOND ? cmp ? IFS_TRUE : IFS_PREFALSE : IFS_POSTFALSE; if (ifsd >= MAXIFSDEPTH-1) badfmt("%?...%. nested too deeply"); ifss[++ifsd] = newifs; } break; case '|': if (ifsd < 1) badfmt("%| without an opening %?"); switch (ifss[ifsd]) { case IFS_PREFALSE: ifss[ifsd] = IFS_TRUE; break; default: ifss[ifsd] = IFS_POSTFALSE; break; } break; case '.': if (ifsd < 1) badfmt("%. without an opening %?"); ifsd --; break; default: badfmt("bad % key character"); break; } } if (ifsd != 0) badfmt("unclosed %?"); *ap = addr; return(DFR_OK); } #undef fn #undef nw #undef opcw #undef dp #undef lasts #undef addr static void dis_bufch(char c) { if (dis_len >= dis_have) dis_buf = realloc(dis_buf,dis_have=(dis_len+16)); dis_buf[dis_len++] = c; } static int do_dis_inst(ADDR addr, void (*fn)(char), CFLAG flg) { ADDR orig; unsigned short int opc; unsigned short int ivv; int printpaddr; addr -= corebase; orig = addr; if (addr+2 > coresize) return(-1); opc = corefetchu(addr,2); addr += 2; ivv = iv[opc]; printpaddr = 1; switch (ivv) { case IV_NIL: case IV_HARD: { int nw; int ix; INSTR *i; int j; ADDR amin; ADDR alast; ADDR a0; ADDR a; int ndid; int deeper; int sizebroke; int didix; unsigned short int wv[MAXWORDS]; INSTR *ivec; int ni; int cansetiv; ivec = &Machine_m68k_instrs[0]; ni = Machine_m68k_ninstrs; cansetiv = 1; if (0) { case IV_COPROC: ivec = Machine_m68k_cptbl[(opc>>9)&7]; ni = Machine_m68k_ncptbl[(opc>>9)&7]; cansetiv = 0; } nw = 0; ndid = 0; a0 = orig; sizebroke = 0; do { if (a0+2 > coresize) { sizebroke = 1; break; } wv[nw++] = corefetchu(a0,2); a0 += 2; deeper = 0; for (ix=0;ixnwords < nw) continue; for (j=0;jwords[j].mask) != i->words[j].cmp) break; if (j < nw) continue; if (i->nwords > nw) { deeper ++; continue; } dis_len = 0; a = a0; switch (dis_fmt(&dis_bufch,nw,&wv[0],&a,i->desc)) { case DFR_OK: didix = ix; if (ndid > 0) { fnprintf(fn," {0x%lx} / ",(unsigned long int)alast); if (a < amin) amin = a; } else { amin = a; } fnprintf(fn,"%.*s",dis_len,dis_buf); ndid ++; alast = a; break; case DFR_OVERRUN: sizebroke = 1; continue; break; case DFR_FORBIDDEN: continue; break; } } } while (deeper); if (ndid < 1) { if (nw == 1) iv[opc] = IV_NONE; if (sizebroke) return(-1); case IV_NONE: switch (opc & 0xf000) { case 0xa000: dis_fmt(fn,1,&opc,&addr,""); break; case 0xf000: dis_fmt(fn,1,&opc,&addr,""); break; default: dis_fmt(fn,1,&opc,&addr,""); break; } addr = orig + 2; } else { if ((ndid == 1) && !sizebroke && cansetiv) { if (nw == 1) { iv[opc] = didix; } else { for (ix=0;ixwords[0].mask) == i->words[0].cmp) && (i->nwords != nw)) break; } if (ix >= ni) { didix = -1; for (ix=0;ixwords[0].mask) == i->words[0].cmp) { if (didix == -1) { didix = ix; } else { didix = -2; } } } if (didix < 0) { iv[opc] = IV_MBYTE(nw); } else { iv[opc] = didix; } } } } if (ndid > 1) { fnprintf(fn," {0x%lx}",(unsigned long int)alast); printpaddr = 0; } if (sizebroke) fnprintf(fn," / (core overrun)"); addr = amin; } } break; default: if (IV_ISMBYTE(ivv)) { int nw; int ix; INSTR *i; int j; ADDR a; ADDR alast; ADDR amin; int ndid; unsigned short int wv[MAXWORDS]; nw = IV_MBYTE_NB(ivv); if (orig+(nw*2) > coresize) return(-1); wv[0] = opc; for (j=1;jnwords != nw) continue; for (j=0;jwords[j].mask) != i->words[j].cmp) break; if (j < nw) continue; dis_len = 0; a = addr; switch (dis_fmt(&dis_bufch,nw,&wv[0],&a,i->desc)) { case DFR_OK: if (ndid > 0) { fnprintf(fn," {0x%lx} / ",(unsigned long int)alast); if (a < amin) amin = a; } else { amin = a; } fnprintf(fn,"%.*s",dis_len,dis_buf); ndid ++; alast = a; break; case DFR_OVERRUN: case DFR_FORBIDDEN: continue; break; } } if (ndid < 1) { fnprintf(fn,""); } else { addr = amin; if (ndid > 1) { fnprintf(fn," {0x%lx}",(unsigned long int)alast); printpaddr = 0; } } } else { INSTR *i; ADDR a; int nw; int j; unsigned short int wv[MAXWORDS]; i = &Machine_m68k_instrs[ivv]; nw = i->nwords; if (nw == 1) { dis_fmt(fn,1,&opc,&addr,i->desc); } else { if (orig+(nw*2) > coresize) return(-1); wv[0] = opc; for (j=1;jdesc)) { case DFR_OK: fnprintf(fn,"%.*s",dis_len,dis_buf); break; case DFR_OVERRUN: return(-1); break; case DFR_FORBIDDEN: { fnprintf(fn,""); } break; } addr = a; } } break; } if (flg & CFF_INST_PARALLEL) { if (printpaddr) fnprintf(fn," {%lx}",(unsigned long int)(corebase+addr)); flags[orig+1] = CF_PREV; addr = orig + 2; } else { int n; int i; n = addr - orig; for (i=1;i",(unsigned long int)flags[addr-corebase]); rv = 1; } return(rv); } static unsigned long int m68k_fetch(const void *base, int size) #define bp(n) ((unsigned long int)(((const unsigned char *)base)[(n)])) { switch (size) { case 1: return(bp(0)); break; case 2: return((bp(0)<<8)|bp(1)); break; case 4: return((bp(0)<<24)|(bp(1)<<16)|(bp(2)<<8)|bp(3)); break; } abort(); } #undef bp static const char *m68k_names[] = { "68k", "M68k", "m68k", "MC68k", "mc68k", 0 }; MACHINE machine_m68k = { &m68k_names[0], 4, &m68k_init, 0, &m68k_dis, &m68k_fetch, 0 };