/* * Author: Christopher G. Phillips * Copyright (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * The author makes no representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. * * Copyright for PILOTDIS - modified from original m68k program * Copyright (C) 1998 David Griffiths * * Copyright for PILOTDIS - modified from original m68k program * Copyright (C) 1999 Nick Spence * * Copyright for PILOTDIS - modified from original m68k program * Copyright (C) 2000 Ali Akcaagac * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * pilotdis' main (which processes command-line arguments) is here, * along with definitions for most global variables. */ /************************************************************************/ /* Copyright for PILOTDIS - modified from original m68k program */ /* Copyright (C) 1998 David Griffiths */ /* */ /* Copyright for PILOTDIS - modified from original m68k program */ /* Copyright (C) 1999 Nick Spence */ /* */ /* Copyright for PILOTDIS - modified from original m68k program */ /* Copyright (C) 2000 Ali Akcaagac */ /************************************************************************/ /************************************************************************/ /* normal includes */ /************************************************************************/ #include #include #include #include #include #include "dis.h" /************************************************************************/ /* version */ /************************************************************************/ char *patchlevel = "1.17"; /************************************************************************/ /* conditioncode */ /************************************************************************/ char *cc[] = { "T", "F", "HI", "LS", "CC", "CS", "NE", "EQ", "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" }; /************************************************************************/ /* bitd */ /************************************************************************/ char *bitd[] = { "TST", "CHG", "CLR", "SET" }; /************************************************************************/ /* bitf */ /************************************************************************/ char *bitf[] = { "EXTU", "EXTS", "FFO", "INS" }; /************************************************************************/ /* buffers for printing instructions */ /************************************************************************/ char buf1[100]; char buf2[100]; char buf3[100]; int pass = 0; int valid = 0; int rtsflag = 0; FILE *infp; FILE *outfp; m68kaddr pc = 0; m68kaddr ppc = 0; m68kaddr initialpc = 0; int chip = 0; int lower = 0; int pilamode = 0; int codeonly = 0; int seperator = 0; int hexonly = 0; int deconly = 0; int verbose = 0; int minlen = 5; int onepass = 0; int sp = 0; int odd = 0; int linkfallthrough = 0; int use_isprint = 0; int fdigits = 6; int globalxref = 0; int labelxref = 0; size_t slenprint = 80; struct global *globals = NULL; #ifndef NOBAD int dobad = 0; #endif char *afile = NULL; char *bfile = NULL; char *ffile = NULL; char *ifile = NULL; char *gfile = NULL; char *jfile = NULL; char *nfile = NULL; char *tfile = NULL; char *nsfile = NULL; jmp_buf jmp; char *sfile; char *vfile; static char *progname; /************************************************************************/ /* usage */ /************************************************************************/ static void usage(void) { fprintf(stderr, "\n\nMotorola 68k Series Disassembler (modified for PalmOS computers) - rev %s\n\n", patchlevel); fprintf(stderr, "Usage: %s\n", progname); fprintf(stderr, " [-help] [-000|-008|-010|-020|-030|-040|-851|-881|-882] [-a A-Line-file]\n"); fprintf(stderr, " [-all[c]] [-pilamode] [-b break-file] [-f F-line-file] [-g globals-file]\n"); fprintf(stderr, " [-i instruction-file] [-isp] [-j jump-file] [-l] [-codeonly] [-seperator]\n"); fprintf(stderr, " [-lft] [-n data-file] [-ng] [-nl] [-ns notstart-file] [-o output-file]\n"); fprintf(stderr, " [-odd] [-pc initialpc] [-s minlength] [-slenp maxlength] [-t traps-file]\n"); fprintf(stderr, " [-hex] [-dec] [-v] file...\n\n\n"); exit(1); } /************************************************************************/ /* help */ /************************************************************************/ static void help(void) { fprintf(stderr, "\n\nMotorola 68k Series Disassembler (modified for PalmOS computers) - rev %s\n\n", patchlevel); fprintf(stderr, "Usage: %s [-help]\n", progname); fprintf(stderr, " [-000|-008|-010] .......: select processor version\n"); fprintf(stderr, " [-020|-030|-040] .......: select processor version\n"); fprintf(stderr, " [-851|-881|-882] .......: select processor version\n"); fprintf(stderr, " [-a A-Line-file] .......: list of added AXXX instruction opcode words\n"); fprintf(stderr, " [-all[c]] ..............: output instructions at all word boundaries\n"); fprintf(stderr, " [-pilamode] ............: generate special pila compatible output\n"); fprintf(stderr, " [-b break-file] ........: list of addresses where new output lines start\n"); fprintf(stderr, " [-bad] .................: print out lines that invalidate instructions\n"); fprintf(stderr, " [-f F-line-file] .......: list of added FXXX instruction opcode words\n"); fprintf(stderr, " [-g globals-file] ......: list of global addresses and labels\n"); fprintf(stderr, " [-i instruction-file] ..: list of instructions start addresses and labels\n"); fprintf(stderr, " [-isp] .................: use local machines definition of ascii range\n"); fprintf(stderr, " [-j jump-file] .........: list of AXXX and FXXX opcodes which always jump\n"); fprintf(stderr, " [-l] ...................: force output to lower case\n"); fprintf(stderr, " [-codeonly] ............: force output of code only\n"); fprintf(stderr, " [-seperator] ...........: add an seperator after RTS\n"); fprintf(stderr, " [-lft] .................: allow opcodes that 'fall-through' to LINK\n"); fprintf(stderr, " [-n data-file] .........: list of data start addresses and labels\n"); fprintf(stderr, " [-ng] ..................: print global xref table\n"); fprintf(stderr, " [-nl] ..................: print label xref table\n"); fprintf(stderr, " [-ns notstart-file] ....: list of addresses which do not start instructions\n"); fprintf(stderr, " [-o output-file] .......: name of file for output\n"); fprintf(stderr, " [-odd] .................: allow opcodes to start on odd byte boundaries\n"); fprintf(stderr, " [-pc initialpc] ........: starting address for program\n"); fprintf(stderr, " [-s minlength] .........: minimum number of ascii data bytes for a string\n"); fprintf(stderr, " [-slenp maxlength] .....: maximum number of ascii chars output on one line\n"); fprintf(stderr, " [-t traps-file] ........: replacement list of PalmOS system traps\n"); fprintf(stderr, " [-hex] .................: convert values from #dec!$hex to #$hex only\n"); fprintf(stderr, " [-dec] .................: convert values from #dec!$hex to #dec only\n"); fprintf(stderr, " [-v] ...................: verbose output. inform you about the progress\n"); fprintf(stderr, " file ...................: path to file to be disassembled\n\n\n"); exit(0); } /************************************************************************/ /* main */ /************************************************************************/ int main(int argc, char **argv) { int status = 0; char *ofile = NULL; progname = argv[0]; while(--argc && **++argv == '-') { /************************************************************************/ /* initial pc */ /************************************************************************/ if(strcmp("-pc", *argv) == 0 && argc--) { initialpc = strtoul(*++argv, NULL, 0); } /************************************************************************/ /* select cputype */ /************************************************************************/ else if(strcmp("-000", *argv) == 0) { chip |= MC68000; } else if(strcmp("-008", *argv) == 0) { chip |= MC68008; } else if(strcmp("-010", *argv) == 0) { chip |= MC68010; } else if(strcmp("-020", *argv) == 0) { chip |= MC68020; } else if(strcmp("-030", *argv) == 0) { chip |= MC68030; } else if(strcmp("-040", *argv) == 0) { chip |= MC68040; } else if(strcmp("-851", *argv) == 0) { chip |= MC68851; } else if(strcmp("-881", *argv) == 0) { chip |= MC68881; } else if(strcmp("-882", *argv) == 0) { chip |= MC68882; } /************************************************************************/ /* output pathname */ /************************************************************************/ else if(strcmp("-o", *argv) == 0 && argc--) { ofile = *++argv; } /************************************************************************/ /* file containing offsets that *are* instruction */ /************************************************************************/ else if(strcmp("-i", *argv) == 0 && argc--) { ifile = *++argv; } /************************************************************************/ /* file containing valid a-line (1010) instructions */ /************************************************************************/ else if(strcmp("-a", *argv) == 0 && argc--) { afile = *++argv; } /************************************************************************/ /* file containing offsets of data for which */ /* a new line of output should be started */ /************************************************************************/ else if(strcmp("-b", *argv) == 0 && argc--) { bfile = *++argv; } /************************************************************************/ /* file containing valid f-line (1111) instructions */ /************************************************************************/ else if(strcmp("-f", *argv) == 0 && argc--) { ffile = *++argv; } /************************************************************************/ /* file containing global labels */ /************************************************************************/ else if(strcmp("-g", *argv) == 0 && argc--) { gfile = *++argv; } /************************************************************************/ /* file containing a-line and f-line instructions that cause pc */ /* to be changed such that it is not necessary for the next word */ /* to be an instruction */ /************************************************************************/ else if(strcmp("-j", *argv) == 0 && argc--) { jfile = *++argv; } /************************************************************************/ /* file containing offsets that are *not* instructions */ /************************************************************************/ else if(strcmp("-n", *argv) == 0 && argc--) { nfile = *++argv; } /************************************************************************/ /* file containing offsets that are not the *start* of */ /* instructions */ /************************************************************************/ else if(strcmp("-ns", *argv) == 0 && argc--) { nsfile = *++argv; } /************************************************************************/ /* file containing known trap #15 routines */ /************************************************************************/ else if(strcmp("-t", *argv) == 0 && argc--) { tfile = *++argv; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-all", *argv) == 0) { onepass = INCONSISTENT; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-allc", *argv) == 0) { onepass = CONSISTENT; } /************************************************************************/ /* fast optimized options for pila */ /************************************************************************/ else if(strcmp("-pilamode", *argv) == 0) { pilamode = 1; codeonly = 1; seperator = 1; hexonly = 1; deconly = 0; verbose = 1; globalxref = 0; labelxref = 0; } /************************************************************************/ /* help */ /************************************************************************/ else if(strcmp("-h", *argv) == 0) { help(); } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-isp", *argv) == 0) { use_isprint = 1; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-lft", *argv) == 0) { linkfallthrough = 1; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-odd", *argv) == 0) { odd = 1; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-ng", *argv) == 0) { globalxref = 1; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-nl", *argv) == 0) { labelxref = 1; } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-sp", *argv) == 0) { sp = 1; } /************************************************************************/ /* force output of lowercase code */ /************************************************************************/ else if(strcmp("-l", *argv) == 0) { lower = 1; } /************************************************************************/ /* force of codeonly output */ /************************************************************************/ else if(strcmp("-codeonly", *argv) == 0) { codeonly = 1; } /************************************************************************/ /* add seperatorline after each rts */ /************************************************************************/ else if(strcmp("-seperator", *argv) == 0) { seperator = 1; } /************************************************************************/ /* force output as hex */ /************************************************************************/ else if(strcmp("-hex", *argv) == 0) { hexonly = 1; } /************************************************************************/ /* force output as dec */ /************************************************************************/ else if(strcmp("-dec", *argv) == 0) { deconly = 1; } /************************************************************************/ /* force of verbose */ /************************************************************************/ else if(strcmp("-v", *argv) == 0) { verbose = 1; } /************************************************************************/ /* */ /************************************************************************/ #ifdef DEBUG else if(strncmp("-d", *argv, 2) == 0) { if(isdigit(argv[0][2])) { debug = atoi(&argv[0][2]); } } #endif /************************************************************************/ /* */ /************************************************************************/ #ifndef NOBAD else if(strcmp("-bad", *argv) == 0) { dobad = 1; } #endif /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-s", *argv) == 0 && argc--) { minlen = atoi(*++argv); if(minlen < 2) { minlen = 2; } } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-fdigits", *argv) == 0 && argc--) { fdigits = atoi(*++argv); if(fdigits < 2) { fdigits = 2; } } /************************************************************************/ /* */ /************************************************************************/ else if(strcmp("-slenp", *argv) == 0 && argc--) { slenprint = atoi(*++argv); if(slenprint < 10) { slenprint = 10; } } /************************************************************************/ /* bad option entered */ /************************************************************************/ else { fprintf(stderr, "%s: bad option: %s\n", progname, *argv); usage(); } } if(!odd && initialpc & 1) { fprintf(stderr, "%s: initialpc odd but -odd not specified\n", progname); exit(1); } /************************************************************************/ /* check if someone wants to fool pilotdis */ /************************************************************************/ if(hexonly && deconly) { if(pilamode) { hexonly = 1; deconly = 0; } else { hexonly = 0; deconly = 0; } } if(!CPU(chip)) { chip |= MC68000; } if(PMMU(chip) && CPU(chip) < MC68020) { fprintf(stderr, "%s: bad cpu/coprocessor combination\n", progname); exit(1); } if(argc == 0 && onepass) { infp = stdin; sfile = vfile = "stdin"; if(setjmp(jmp) == 0) { disassemble(); } } else if(argc == 1 || argc > 1 && !ofile) { argv--; while(argc--) { char *lastslash; size_t len; size_t extra; if((infp = fopen(*++argv, "rb")) == NULL) { perror(*argv); status++; continue; } /************************************************************************/ /* determine output filename. if unspecified, add ".s" to end */ /* of input filename. */ /************************************************************************/ if(ofile) { sfile = ofile; } else { lastslash = strrchr(*argv, '/'); if(lastslash) { *argv = lastslash + 1; } len = strlen(*argv); extra = (len > 2 && argv[0][len - 2] == '.' && argv[0][len - 1] == 'o') ? 0 : 2; if((sfile = malloc(len + extra + 1)) == NULL) { perror(*argv); status++; (void)fclose(infp); continue; } strcpy(sfile, *argv); strcpy(&sfile[len - 2 + extra], ".s"); } vfile = *argv; if((outfp = fopen(sfile, "w")) == NULL) { perror(sfile); status++; (void)fclose(infp); continue; } if(setjmp(jmp) == 0) { disassemble(); } (void)fclose(infp); (void)fclose(outfp); if(!ofile) { free(sfile); } } } else { usage(); } return(status); }