├── Makefile ├── MAC ├── Makefile ├── maken.pl ├── makeb.pl ├── mac2.pl ├── makes ├── mac.pl ├── rftos.pl ├── mac.odd ├── rf.c └── mac.0189 ├── wierd ├── hex.c ├── README ├── addr.h ├── afline.c ├── main.c ├── dis.h ├── pgen.c ├── m68kdis.1 ├── fgen.c ├── inst1.c ├── README.md ├── utils.c └── inst2.c /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-DDEBUG -g -D_ANSI_C_SOURCE 2 | LIBS=-lm 3 | SRCS=dis.c inst1.c inst2.c main.c utils.c afline.c pgen.c fgen.c 4 | OBJS=$(SRCS:.c=.o) 5 | PROG=m68kdis 6 | 7 | $(PROG): $(OBJS) 8 | $(CC) -o $@ $(OBJS) $(LIBS) 9 | 10 | $(OBJS): dis.h 11 | inst2.o fgen.o pgen.o: addr.h 12 | 13 | hex: hex.o 14 | $(CC) -o $@ hex.o 15 | 16 | clean: 17 | -rm -f $(PROG) $(OBJS) hex hex.o 18 | -------------------------------------------------------------------------------- /MAC/Makefile: -------------------------------------------------------------------------------- 1 | all: mac.a mac.j rf 2 | @wd=`pwd`; \ 3 | i=`grep '^MACDIR=' makes | sed -e 's/.*=[ ]*//' -e 's/[ ]*$$//'`; \ 4 | if [ "X$$i" = "X" -o "X`eval echo $$i`" != "X$$wd" ]; \ 5 | then echo Change MACDIR in makes to $$wd; \ 6 | fi 7 | 8 | rf: rf.o 9 | $(CC) -o $@ rf.o 10 | 11 | mac.a: mac.0189 12 | perl mac.pl mac.0189 | perl mac2.pl mac.odd > mac.a 13 | 14 | mac.j: mac.a 15 | grep _ExitToShell mac.a | awk '{printf("0x%s\n", $$1)}' > mac.j 16 | -------------------------------------------------------------------------------- /wierd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | grep '4e75' $* | grep -v RTS | grep '^[0-9a-f]*[ ][ ]*[0-9a-f]*4e75' > /tmp/$$ 4 | grep '4e5e' $* | grep -v UNLK | grep '^[0-9a-f]*[ ][ ]*[0-9a-f]*4e5e' >> /tmp/$$ 5 | grep '4e56' $* | grep -v LINK | grep '^[0-9a-f]*[ ][ ]*[0-9a-f]*4e56' >> /tmp/$$ 6 | #grep '\(PC\)' $* >> /tmp/$$ 7 | if [ -s /tmp/$$ ] 8 | then 9 | echo "$0: possible problems" 10 | echo "----------------------------------------------------------------" 11 | sort -u /tmp/$$ 12 | fi | more 13 | rm /tmp/$$ 14 | -------------------------------------------------------------------------------- /MAC/maken.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | # Author: Christopher G. Phillips 4 | # Copyright (C) 1994 All Rights Reserved 5 | # 6 | # NOTICE 7 | # 8 | # Permission to use, copy, modify, and distribute this software and 9 | # its documentation for any purpose and without fee is hereby granted 10 | # provided that the above copyright notice appear in all copies and 11 | # that both the copyright notice and this permission notice appear in 12 | # supporting documentation. 13 | # 14 | # The author makes no representations about the suitability of this 15 | # software for any purpose. This software is provided ``as is'' 16 | # without express or implied warranty. 17 | 18 | while (<>) { 19 | if (/^Bytes ([0-9a-fA-F]+) to [0-9a-fA-F]+$/) { 20 | printf("0x%lx\n", hex($1) - 4); 21 | printf("0x%lx\n", hex($1) - 2); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MAC/makeb.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | # Author: Christopher G. Phillips 4 | # Copyright (C) 1994 All Rights Reserved 5 | # 6 | # NOTICE 7 | # 8 | # Permission to use, copy, modify, and distribute this software and 9 | # its documentation for any purpose and without fee is hereby granted 10 | # provided that the above copyright notice appear in all copies and 11 | # that both the copyright notice and this permission notice appear in 12 | # supporting documentation. 13 | # 14 | # The author makes no representations about the suitability of this 15 | # software for any purpose. This software is provided ``as is'' 16 | # without express or implied warranty. 17 | 18 | while (<>) { 19 | if (/^Bytes ([0-9a-fA-F]+) to ([0-9a-fA-F]+)$/) { 20 | printf("0x%lx\n", hex($1) - 4); 21 | printf("0x%lx\n", hex($1)); 22 | printf("0x%lx\n", hex($2) + 1); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MAC/mac2.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | # Author: Christopher G. Phillips 4 | # Copyright (C) 1994 All Rights Reserved 5 | # 6 | # NOTICE 7 | # 8 | # Permission to use, copy, modify, and distribute this software and 9 | # its documentation for any purpose and without fee is hereby granted 10 | # provided that the above copyright notice appear in all copies and 11 | # that both the copyright notice and this permission notice appear in 12 | # supporting documentation. 13 | # 14 | # The author makes no representations about the suitability of this 15 | # software for any purpose. This software is provided ``as is'' 16 | # without express or implied warranty. 17 | 18 | while (<>) { 19 | chop; 20 | if (/^(a[0-9a-f]{3})\s+(\S.*)$/i) { 21 | $s = $2; 22 | $s =~ s/\s+$//; 23 | $t = $1; 24 | $t =~ tr/A-Z/a-z/; 25 | $name{"$t"} = $s; 26 | } 27 | } 28 | 29 | while () { 30 | if (/^(a[0-9a-f]{3})\s+/i) { 31 | $trap = $1; 32 | $trap =~ tr/A-Z/a-z/; 33 | if (defined $name{"$trap"}) { 34 | $v = $name{"$trap"}; 35 | print "$trap $v\n"; 36 | undef $v; 37 | next; 38 | } 39 | } 40 | print; 41 | } 42 | 43 | foreach $key (sort byhex (keys %name)) { 44 | $v = $name{"$key"}; 45 | print "$key $v\n"; 46 | } 47 | 48 | sub byhex { 49 | hex($a) - hex($b); 50 | } 51 | -------------------------------------------------------------------------------- /MAC/makes: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | 3 | # Author: Christopher G. Phillips 4 | # Copyright (C) 1994 All Rights Reserved 5 | # 6 | # NOTICE 7 | # 8 | # Permission to use, copy, modify, and distribute this software and 9 | # its documentation for any purpose and without fee is hereby granted 10 | # provided that the above copyright notice appear in all copies and 11 | # that both the copyright notice and this permission notice appear in 12 | # supporting documentation. 13 | # 14 | # The author makes no representations about the suitability of this 15 | # software for any purpose. This software is provided ``as is'' 16 | # without express or implied warranty. 17 | 18 | MACDIR=. 19 | 20 | if [ $# -ne 1 ] 21 | then 22 | echo Usage: $0 file.rf 23 | exit 1 24 | fi 25 | if [ ! -f $1.out ] 26 | then 27 | $MACDIR/rf $1.rf > $1.out 28 | fi 29 | if [ ! -f $1.b ] 30 | then 31 | $MACDIR/makeb.pl < $1.out > $1.b 32 | fi 33 | if [ ! -f $1.n ] 34 | then 35 | $MACDIR/maken.pl < $1.out > $1.n 36 | fi 37 | args="-s 4 -sp -odd -a $MACDIR/mac.a -j $MACDIR/mac.j -b $1.b -n $1.n -030 -881 -lft" 38 | if [ -f $1.i ] 39 | then 40 | args="$args -i $1.i" 41 | fi 42 | if [ -f $1.f ] 43 | then 44 | args="$args -f $1.f" 45 | fi 46 | if [ -f $1.ns ] 47 | then 48 | args="$args -ns $1.ns" 49 | fi 50 | $MACDIR/../m68kdis $args $1.rf 2> $1.rf.stderr 51 | $MACDIR/rftos.pl $1 52 | $MACDIR/../wierd $1.rf.s | more 53 | exit 0 54 | 55 | # whybad.pl < d2 | worst.pl $1.n | more 56 | -------------------------------------------------------------------------------- /hex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | char 22 | getachar(void) 23 | { 24 | int first = 1; 25 | char result = 0; 26 | int c; 27 | 28 | while ((c = getchar()) != EOF) { 29 | if (c >= '0' && c <= '9') 30 | if (first) { 31 | result = (c - '0') << 4; 32 | first = 0; 33 | } else { 34 | result |= c - '0'; 35 | return result; 36 | } 37 | if (c >= 'A' && c <= 'F') 38 | if (first) { 39 | result = (c - 'A' + 10) << 4; 40 | first = 0; 41 | } else { 42 | result |= c - 'A' + 10; 43 | return result; 44 | } 45 | if (c >= 'a' && c <= 'f') 46 | if (first) { 47 | result = (c - 'a' + 10) << 4; 48 | first = 0; 49 | } else { 50 | result |= c - 'a' + 10; 51 | return result; 52 | } 53 | } 54 | 55 | exit(0); 56 | } 57 | 58 | int 59 | main(int argc, char **argv) 60 | { 61 | char c; 62 | 63 | while (1) { 64 | c = getachar(); 65 | putchar(c); 66 | fflush(stdout); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | m68kdis - disassemble Motorola 68000 family object code 2 | 3 | m68kdis is a disassembler for the Motorola 68000 family of cpu chips 4 | (currently up to the 68030). The disassembler attempts to discern 5 | between the instruction and data portions of an object code file. 6 | 7 | Make sure you use an ANSI C compiler with full prototypes. Then type 8 | ``make'' to build m68kdis. If you want the Macintosh stuff, run make 9 | in the MAC directory also (you will need perl). 10 | 11 | There are two methods provided for debugging. The script ``wierd'' can 12 | be used; it seeks to point out LINK, UNLK, and RTS instructions that 13 | ended up being data. If you think these were so interpreted 14 | incorrectly, you can use the -bad (which writes to standard error) or 15 | -all options to help figure this out. 16 | 17 | MAC-SPECIFIC STUFF 18 | ------------------ 19 | There's a file for A-line instructions for the Macintosh (MAC/mac.a). 20 | It undoubtedly is not complete and/or accurate for your code. Often 21 | code that uses an A-line instruction not currently known will result in 22 | problems spotted by ``wierd''. ``mac.0189'' is the file to add new 23 | instructions to (the lines must match /^a[0189]/). ``mac.odd'' is for 24 | instructions that contradict mac.0189. After editing, rerun make. 25 | 26 | Four scripts, ``makes'', ``rftos.pl'', ``makeb.pl'', and ``maken.pl'', 27 | and the C program ``rf'' are provided to make it easier to format the 28 | output for a resource fork in a more Mac-friendly fashion. A resource 29 | fork should be named .rf and ``makes'' should be called with the 30 | lone argument . 31 | 32 | Suggestions and questions welcome. 33 | 34 | Chris 35 | Christopher_Phillips@pe.utexas.edu 36 | -------------------------------------------------------------------------------- /MAC/mac.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | # Author: Christopher G. Phillips 4 | # Copyright (C) 1994 All Rights Reserved 5 | # 6 | # NOTICE 7 | # 8 | # Permission to use, copy, modify, and distribute this software and 9 | # its documentation for any purpose and without fee is hereby granted 10 | # provided that the above copyright notice appear in all copies and 11 | # that both the copyright notice and this permission notice appear in 12 | # supporting documentation. 13 | # 14 | # The author makes no representations about the suitability of this 15 | # software for any purpose. This software is provided ``as is'' 16 | # without express or implied warranty. 17 | 18 | while (<>) { 19 | if (/^(a([0189])[0-9a-fA-F]{2})\s+(.+)\s*$/) { 20 | $s = $3; 21 | $inst = $1; 22 | $inst =~ tr/A-Z/a-z/; 23 | $c = $2; 24 | if ($c =~ /0/) { 25 | $zero{"$inst"} = $s; 26 | } elsif ($c =~ /1/) { 27 | $one{"$inst"} = $s; 28 | } elsif ($c =~ /8/) { 29 | $eight{"$inst"} = $s; 30 | } else { 31 | $nine{"$inst"} = $s; 32 | } 33 | } 34 | } 35 | 36 | foreach $key (sort byhex (keys %zero)) { 37 | $key =~ /^a0(..)/ && ($last2 = $1); 38 | $v = $zero{"$key"}; 39 | if (defined $one{"$key"}) { 40 | for ($i = 0; $i < 8; $i += 2) { 41 | print "a$i$last2 $v\n"; 42 | } 43 | $v = $one{"$key"}; 44 | for ($i = 1; $i < 8; $i += 2) { 45 | print "a$i$last2 $v\n"; 46 | } 47 | undef $one{"$key"}; 48 | } else { 49 | for ($i = 0; $i < 8; $i++) { 50 | print "a$i$last2 $v\n"; 51 | } 52 | } 53 | } 54 | foreach $key (sort byhex (keys %one)) { 55 | $key =~ /^a1(..)/ && ($last2 = $1); 56 | $v = $one{"$key"}; 57 | for ($i = 1; $i < 8; $i++) { 58 | print "a$i$last2 $v\n"; 59 | } 60 | } 61 | foreach $key (sort byhex (keys %eight)) { 62 | $key =~ /^a8(..)/ && ($last2 = $1); 63 | $v = $eight{"$key"}; 64 | print "a8$last2 $v\n"; 65 | print "aa$last2 $v\n"; 66 | print "ac$last2 $v\n"; 67 | print "ae$last2 $v\n"; 68 | } 69 | foreach $key (sort byhex (keys %nine)) { 70 | $key =~ /^a9(..)/ && ($last2 = $1); 71 | $v = $nine{"$key"}; 72 | print "a9$last2 $v\n"; 73 | print "ab$last2 $v\n"; 74 | print "ad$last2 $v\n"; 75 | print "af$last2 $v\n"; 76 | } 77 | exit(0); 78 | 79 | sub byhex { 80 | hex($a) - hex($b); 81 | } 82 | -------------------------------------------------------------------------------- /MAC/rftos.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | 3 | # Author: Christopher G. Phillips 4 | # Copyright (C) 1994 All Rights Reserved 5 | # 6 | # NOTICE 7 | # 8 | # Permission to use, copy, modify, and distribute this software and 9 | # its documentation for any purpose and without fee is hereby granted 10 | # provided that the above copyright notice appear in all copies and 11 | # that both the copyright notice and this permission notice appear in 12 | # supporting documentation. 13 | # 14 | # The author makes no representations about the suitability of this 15 | # software for any purpose. This software is provided ``as is'' 16 | # without express or implied warranty. 17 | 18 | if ($#ARGV == 0) { 19 | $file = $ARGV[0]; 20 | open(INFILE, "<$file.rf.s") || die "$file.rf.s: $!\n"; 21 | die if system("mv", "${file}.rf.s", "$file.rf.s.$$"); 22 | open(OUTFILE, ">$file.rf.s") || die "$file.rf.s: $!\n"; 23 | open(RF, "<$file.out") || die "$file.out: $!\n"; 24 | $n = 0; 25 | while () { 26 | if (/^Resource type: "(....)"$/) { 27 | $type = $1; 28 | } elsif (/^ID (\d+)$/) { 29 | $id = $1; 30 | } elsif (/^Bytes ([0-9a-fA-F]+) to ([0-9a-fA-F]+)$/) { 31 | $start = sprintf("%08lx", hex($1) - 4); 32 | $assoc{"$start"} = sprintf("%4.4s %d", $type, $id); 33 | $ends{"$start"} = sprintf("%08lx", hex($2) + 1); 34 | } 35 | } 36 | close(RF); 37 | 38 | @keys = sort keys %assoc; 39 | if ($#keys == -1) { 40 | $n = -1; 41 | } else { 42 | $n = 0; 43 | $key = $keys[$n]; 44 | $value = $assoc{"$key"}; 45 | } 46 | $inresource = 0; 47 | $newline = 0; 48 | select OUTFILE; 49 | while () { 50 | if ($inresource) { 51 | $doit = 0; 52 | if (/^$end/) { 53 | $doit = 1; 54 | } else { 55 | if (hex($_) > $k) { 56 | $doit = 1; 57 | warn "$assoc{$keys[$n - 1]} should not include $end\n"; 58 | } 59 | } 60 | if ($doit) { 61 | print "\n"; 62 | $newline = 1; 63 | $inresource = 0; 64 | } 65 | } 66 | if (!$inresource && $n >= 0 && /^$key/) { 67 | if (!$newline && hex($key) > 0) { 68 | print "\n"; 69 | } 70 | print "$value\n"; 71 | $end = $ends{"$key"}; 72 | $k = hex($end); 73 | if (++$n > $#keys) { 74 | $n = -1; 75 | } else { 76 | $key = $keys[$n]; 77 | $value = $assoc{"$key"}; 78 | } 79 | $inresource = 1; 80 | } 81 | $newline = 0; 82 | print; 83 | } 84 | if ($inresource) { 85 | warn "$value starts at $key but should not include $end\n"; 86 | } 87 | close(INFILE); 88 | close(OUTFILE); 89 | unlink("$file.rf.s.$$"); 90 | } 91 | -------------------------------------------------------------------------------- /addr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * This file contains macros that test whether mode-register combinations 20 | * match commonly used categories of addressing modes. 21 | */ 22 | 23 | #define ISDATA(m) ((m) == 0) 24 | #define ISDIRECT(m) ((m) == 1) 25 | #define ISINDIRECT(m) ((m) == 2) 26 | #define ISPOST(m) ((m) == 3) 27 | #define ISPRE(m) ((m) == 4) 28 | #define ISDISP(m) ((m) == 5) 29 | #define ISINDEX(m) ((m) == 6) 30 | #define ISSHORT(m,r) ((m) == 7 && (r) == 0) 31 | #define ISLONG(m,r) ((m) == 7 && (r) == 1) 32 | #define ISPCDISP(m,r) ((m) == 7 && (r) == 2) 33 | #define ISPCINDEX(m,r) ((m) == 7 && (r) == 3) 34 | #define ISIMM(m,r) ((m) == 7 && (r) == 4) 35 | 36 | /* alterable data */ 37 | #define ISADEA(m,r) (ISDATA(m) | ISINDIRECT(m) | ISPOST(m) | ISPRE(m) \ 38 | | ISDISP(m) | ISINDEX(m) | ISSHORT(m,r) | ISLONG(m,r)) 39 | 40 | /* data minus immediate */ 41 | #define ISDEAlessIMM(m,r) (ISADEA(m,r) | ISPCDISP(m,r) | ISPCINDEX(m,r)) 42 | 43 | /* data */ 44 | #define ISDEA(m,r) (ISDEAlessIMM(m,r) | ISIMM(m,r)) 45 | 46 | /* alterable memory */ 47 | #define ISAMEA(m,r) (ISINDIRECT(m) | ISPOST(m) | ISPRE(m) | ISDISP(m) \ 48 | | ISINDEX(m) | ISSHORT(m,r) | ISLONG(m,r)) 49 | 50 | /* memory */ 51 | #define ISMEA(m,r) (ISAMEA(m,r) | ISIMM(m,r) | ISPCDISP(m,r) \ 52 | | ISPCINDEX(m,r)) 53 | 54 | /* alterable */ 55 | #define ISAEA(m,r) (ISADEA(m,r) | ISDIRECT(m)) 56 | 57 | /* all */ 58 | #define ISALLEA(m,r) (ISDEA(m,r) | ISDIRECT(m)) 59 | 60 | /* alterable control */ 61 | #define ISACEA(m,r) (ISINDIRECT(m) | ISDISP(m) | ISINDEX(m) | ISSHORT(m,r) \ 62 | | ISLONG(m,r)) 63 | 64 | /* alterable control plus predecrement */ 65 | #define ISACEAplusPRE(m,r) (ISACEA(m,r) | ISPRE(m)) 66 | 67 | /* control */ 68 | #define ISCEA(m,r) (ISACEA(m,r) | ISPCDISP(m,r) | ISPCINDEX(m,r)) 69 | 70 | /* control plus postincrement */ 71 | #define ISCEAplusPOST(m,r) (ISCEA(m,r) | ISPOST(m)) 72 | 73 | /* alterable data minus data */ 74 | #define ISADEAlessDATA(m,r) (ISINDIRECT(m) | ISPOST(m) | ISPRE(m) \ 75 | | ISDISP(m) | ISINDEX(m) | ISSHORT(m,r) | ISLONG(m,r)) 76 | -------------------------------------------------------------------------------- /MAC/mac.odd: -------------------------------------------------------------------------------- 1 | a200 _HOpen 2 | a208 _HCreate 3 | a209 _HDelete 4 | a20a _HOpenRF 5 | a20b _HRename 6 | a210 _AllocContig 7 | a214 _HGetVol 8 | a215 _HSetVol 9 | a241 _HSetFLock 10 | a242 _HRstFLock 11 | a256 _StripText 12 | a260 _HFSDispatch 13 | a285 _IdleUpdate 14 | a28a _SlpQInstall 15 | a3ad _NewGestalt 16 | a456 _UpperText 17 | a458 _InsXTime 18 | a485 _IdleState 19 | a48a _SlpQRemove 20 | a5ad _ReplaceGestalt 21 | a656 _StripUpperText 22 | a685 _SerialPower 23 | aa00 _OpenCPort 24 | aa01 _InitCPort 25 | aa03 _NewPixMap 26 | aa04 _DisposPixMap 27 | aa05 _CopyPixMap 28 | aa06 _SetCPortPix 29 | aa07 _NewPixPat 30 | aa08 _DisposPixPat 31 | aa09 _CopyPixPat 32 | aa0a _PenPixPat 33 | aa0b _DackPixPat 34 | aa0c _GetPixPat 35 | aa0d _MakeRGBPat 36 | aa0e _FillCRect 37 | aa0f _FillCOval 38 | aa10 _FillCRoundRect 39 | aa11 _FillCArc 40 | aa12 _FillCRgn 41 | aa13 _FillCPoly 42 | aa14 _RGBForeColor 43 | aa15 _RGBBackColor 44 | aa16 _SetCPixel 45 | aa17 _GetCPixel 46 | aa18 _GetCTable 47 | aa19 _GetForeColor 48 | aa1a _GetBackColor 49 | aa1b _GetCCursor 50 | aa1c _SetCCursor 51 | aa1d _AllocCursor 52 | aa1e _GetCIcon 53 | aa1f _PlotCIcon 54 | aa20 _OpenCPicture 55 | aa21 _OpColor 56 | aa22 _HiliteColor 57 | aa23 _CharExtra 58 | aa24 _DisposCTable 59 | aa25 _DisposCIcon 60 | aa26 _DisposCCursor 61 | aa27 _GetMaxDevice 62 | aa29 _GetDeviceList 63 | aa2a _GetMainDevice 64 | aa2b _GetNextDevice 65 | aa2c _TestDeviceAttribute 66 | aa2d _SetDeviceAttribute 67 | aa2e _InitGDevice 68 | aa2f _NewGDevice 69 | aa30 _DisposGDevice 70 | aa31 _SetGDevice 71 | aa32 _GetGDevice 72 | aa33 _Color2Index 73 | aa34 _Index2Color 74 | aa35 _InvertColor 75 | aa36 _RealColor 76 | aa37 _GetSubTable 77 | aa39 _MakeITable 78 | aa3a _AddSearch 79 | aa3b _AddComp 80 | aa3c _SetClientID 81 | aa3d _ProtectEntry 82 | aa3e _ReserveEntry 83 | aa3f _SetEntries 84 | aa40 _QDError 85 | aa41 _SetWinColor 86 | aa42 _GetAuxWin 87 | aa43 _SetCtlColor 88 | aa44 _GetAuxCtl 89 | aa45 _NewCWindow 90 | aa46 _GetNewCWindow 91 | aa47 _SetDeskCPat 92 | aa48 _GetCWMgrPort 93 | aa49 _SaveEntries 94 | aa4a _RestoreEntries 95 | aa4b _NewCDialog 96 | aa4c _DelSearch 97 | aa4d _DelComp 98 | aa4f _CalcCMask 99 | aa50 _SeedCFill 100 | aa51 _CopyDeepMask 101 | aa52 _HighLevelFSDispatch 102 | aa60 _DelMCEntries 103 | aa61 _GetMCInfo 104 | aa62 _SetMCInfo 105 | aa63 _DispMCInfo 106 | aa64 _GetMCEntry 107 | aa65 _SetMCEntry 108 | aa66 _MenuChoice 109 | aa90 _InitPalettes 110 | aa91 _NewPalette 111 | aa92 _GetNewPalette 112 | aa93 _DisposePalette 113 | aa94 _ActivatePalette 114 | aa95 _NSetPalette 115 | aa96 _GetPalette 116 | aa97 _PmForeColor 117 | aa98 _PmBackColor 118 | aa99 _AnimateEntry 119 | aa9a _AnimatePalette 120 | aa9b _GetEntryColor 121 | aa9c _SetEntryColor 122 | aa9d _GetEntryUsage 123 | aa9f _CTab2Palette 124 | aaa0 _Palette2CTab 125 | aaa1 _PaletteDispatch 126 | ab1d _QDExtensions 127 | abca _DeviceLoop 128 | -------------------------------------------------------------------------------- /afline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * The functions in this file customize the behavior of m68kdis 20 | * to take certain word values as acceptable A-line and F-line 21 | * instructions and whether any of these unconditionally change PC. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "dis.h" 29 | 30 | #define F 0 31 | #define A 1 32 | 33 | struct afinst { 34 | word_t inst; 35 | char *name; 36 | }; 37 | 38 | static int 39 | afsort(const void *v1, const void *v2) 40 | { 41 | struct afinst *p1 = (struct afinst *)v1; 42 | struct afinst *p2 = (struct afinst *)v2; 43 | 44 | if (p1->inst < p2->inst) 45 | return -1; 46 | else if (p1->inst > p2->inst) 47 | return 1; 48 | else 49 | return 0; 50 | } 51 | 52 | static size_t njinsts = 0; 53 | static word_t *jinsts = NULL; 54 | 55 | /* 56 | * Read through ``jfile'' and collect instruction values in ``jinsts''. 57 | */ 58 | static void 59 | readjfile(void) 60 | { 61 | FILE *jfp; 62 | char buf[80]; 63 | char *cp; 64 | word_t ul; 65 | word_t *jtmp; 66 | 67 | if (jfp = fopen(jfile, "r")) { 68 | while (fgets(buf, sizeof buf, jfp)) { 69 | buf[strlen(buf) - 1] = '\0'; /* zap '\n' */ 70 | ul = strtoul(buf, &cp, 16); 71 | if (cp == buf 72 | || !((ul >= 0xa000 && ul <= 0xafff) 73 | || (ul >= 0xf000 && ul <= 0xffff))) { 74 | fprintf(stderr, "%s: File %s: bad inst: %s\n", 75 | sfile, jfile, buf); 76 | continue; 77 | } 78 | if ((jtmp = realloc(jinsts, 79 | ++njinsts * sizeof(*jinsts))) == NULL) { 80 | if (jtmp) 81 | jinsts = jtmp; 82 | perror("realloc"); 83 | (void)fclose(jfp); 84 | return; 85 | } else { 86 | jinsts = jtmp; 87 | jinsts[njinsts - 1] = ul; 88 | } 89 | } 90 | (void)fclose(jfp); 91 | } else 92 | perror(jfile); 93 | } 94 | 95 | /* 96 | * Test whether ``word'' matches an instruction value in ``jfile''. 97 | */ 98 | static int 99 | itsajinst(word_t word) 100 | { 101 | size_t i; 102 | 103 | for (i = 0; i < njinsts; i++) 104 | if (word == jinsts[i]) 105 | return 1; 106 | 107 | return 0; 108 | } 109 | 110 | /* 111 | * Test whether ``word'' is a valid A- or F-line instruction, 112 | * reading ``[af]file'' as necessary. 113 | */ 114 | static char * 115 | validafinst(int anotf, word_t word) 116 | { 117 | static int fileread[2] = { 0, 0 }; 118 | static size_t ninsts[2] = { 0, 0 }; 119 | static struct afinst *afinsts[2] = { NULL, NULL }; 120 | struct afinst *aftmp; 121 | size_t i; 122 | static int jfileread = 0; 123 | 124 | if (anotf && !afile || !anotf && !ffile) 125 | return NULL; 126 | 127 | /* 128 | * Read ``jfile'' if necessary. 129 | */ 130 | if (jfile && !jfileread) { 131 | readjfile(); 132 | jfileread = 1; 133 | } 134 | 135 | /* 136 | * Read ``[af]file'' if necessary, collecting the values 137 | * in ``[af]insts'' and then sorting them. 138 | */ 139 | if (!fileread[anotf]) { 140 | FILE *afp; 141 | 142 | fileread[anotf] = 1; 143 | if (afp = fopen(anotf ? afile : ffile, "r")) { 144 | char afbuf[80]; 145 | word_t ul; 146 | char *cp; 147 | 148 | while (fgets(afbuf, sizeof afbuf, afp)) { 149 | afbuf[strlen(afbuf) - 1] = '\0'; /* zap '\n' */ 150 | ul = strtoul(afbuf, &cp, 16); 151 | if (cp == afbuf 152 | || (anotf && (ul < 0xa000 || ul > 0xafff)) 153 | || (!anotf && (ul < 0xf000 || ul > 0xffff))) { 154 | fprintf(stderr, 155 | "%s: File %s: bad inst: %s\n", sfile, 156 | anotf ? afile : ffile, afbuf); 157 | continue; 158 | } 159 | 160 | /* 161 | * Find instruction-string. 162 | * Use "UNKNOWN" if not given. 163 | */ 164 | cp--; 165 | while (*++cp && isspace(*cp)) 166 | ; 167 | if (!cp) 168 | cp = "UNKNOWN"; 169 | 170 | if ((aftmp = realloc(afinsts[anotf], 171 | ++ninsts[anotf] * sizeof(*afinsts[anotf]))) 172 | == NULL 173 | || (aftmp[ninsts[anotf] - 1].name 174 | = malloc(strlen(cp) + 1)) == NULL) { 175 | if (aftmp) 176 | afinsts[anotf] = aftmp; 177 | perror("realloc"); 178 | return NULL; 179 | } else { 180 | afinsts[anotf] = aftmp; 181 | afinsts[anotf][ninsts[anotf] - 1].inst 182 | = ul; 183 | strcpy( 184 | afinsts[anotf][ninsts[anotf] - 1].name, 185 | cp); 186 | } 187 | } 188 | (void)fclose(afp); 189 | qsort(afinsts[anotf], ninsts[anotf], 190 | sizeof(*afinsts[anotf]), afsort); 191 | } else 192 | perror(anotf ? afile : ffile); 193 | } 194 | for (i = 0; i < ninsts[anotf]; i++) 195 | if (word == afinsts[anotf][i].inst) 196 | return afinsts[anotf][i].name; 197 | 198 | return NULL; 199 | } 200 | 201 | /* 202 | * Verify whether ``word'' is an acceptable A-line instruction. 203 | * Print as necessary. 204 | */ 205 | void 206 | aline(word_t word) 207 | { 208 | char *cp; 209 | 210 | if (cp = validafinst(A, word)) { 211 | instprint(ops2f(0), cp); 212 | valid = 1; 213 | if (itsajinst(word)) 214 | flags |= ISJMP; 215 | } 216 | } 217 | 218 | /* 219 | * Verify whether ``word'' is an acceptable F-line instruction. 220 | * Print as necessary. 221 | */ 222 | void 223 | fline(word_t word) 224 | { 225 | char *cp; 226 | 227 | if (cp = validafinst(F, word)) { 228 | instprint(ops2f(0), cp); 229 | valid = 1; 230 | if (itsajinst(word)) 231 | flags |= ISJMP; 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * m68kdis' main (which processes command-line arguments) is here, 20 | * along with definitions for most global variables. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "dis.h" 29 | 30 | static char *patchlevel = "m68kdis 1.0"; 31 | 32 | char *cc[] = { 33 | "T", "F", "HI", "LS", "CC", "CS", "NE", "EQ", 34 | "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" 35 | }; 36 | char *bitd[] = { 37 | "TST", "CHG", "CLR", "SET" 38 | }; 39 | char *bitf[] = { 40 | "EXTU", "EXTS", "FFO", "INS" 41 | }; 42 | 43 | /* 44 | * Buffers for printing instructions 45 | */ 46 | char buf1[100]; 47 | char buf2[100]; 48 | char buf3[100]; 49 | 50 | addr_t curlabel = 0; 51 | int pass; 52 | int valid; 53 | 54 | FILE *infp; 55 | FILE *outfp; 56 | addr_t pc = 0; 57 | addr_t ppc = 0; 58 | addr_t initialpc = 0; 59 | int chip = 0; 60 | int lower = 0; 61 | int minlen = 5; 62 | int onepass = 0; 63 | int sp = 0; 64 | int odd = 0; 65 | int linkfallthrough = 0; 66 | size_t slenprint = 30; 67 | #ifndef NOBAD 68 | int dobad = 0; 69 | #endif 70 | char *afile = NULL; 71 | char *bfile = NULL; 72 | char *ffile = NULL; 73 | char *ifile = NULL; 74 | char *jfile = NULL; 75 | char *nfile = NULL; 76 | char *nsfile = NULL; 77 | 78 | jmp_buf jmp; 79 | char *sfile; 80 | 81 | static char *progname; 82 | 83 | static void 84 | usage(void) 85 | { 86 | fprintf(stderr, 87 | "Usage: %s [-00|-08|-10|-20|-30] [-a A-line-file] [-all[c]]\n", progname); 88 | fprintf(stderr, 89 | "[-b break-file] [-f F-line-file] [-i instruction-file] [-j jump-file] [-l]\n"); 90 | fprintf(stderr, 91 | "[-lft] [-n data-file] [-ns notstart-file] [-o output-file] [-odd]\n"); 92 | fprintf(stderr, 93 | "[-pc initialpc] [-s minlength] [-slenp maxlength] file...\n"); 94 | exit(1); 95 | } 96 | 97 | int 98 | main(int argc, char **argv) 99 | { 100 | int status = 0; 101 | char *ofile = NULL; 102 | 103 | progname = argv[0]; 104 | 105 | while (--argc && **++argv == '-') { 106 | if (strcmp("-pc", *argv) == 0 && argc--) { 107 | initialpc = strtoul(*++argv, NULL, 0); 108 | } else if (strcmp("-000", *argv) == 0) { 109 | chip |= MC68000; 110 | } else if (strcmp("-008", *argv) == 0) { 111 | chip |= MC68008; 112 | } else if (strcmp("-010", *argv) == 0) { 113 | chip |= MC68010; 114 | } else if (strcmp("-020", *argv) == 0) { 115 | chip |= MC68020; 116 | } else if (strcmp("-030", *argv) == 0) { 117 | chip |= MC68030; 118 | } else if (strcmp("-040", *argv) == 0) { 119 | chip |= MC68040; 120 | } else if (strcmp("-851", *argv) == 0) { 121 | chip |= MC68851; 122 | } else if (strcmp("-881", *argv) == 0) { 123 | chip |= MC68881; 124 | } else if (strcmp("-882", *argv) == 0) { 125 | chip |= MC68882; 126 | } else if (strcmp("-o", *argv) == 0 && argc--) { 127 | /* 128 | * output pathname 129 | */ 130 | ofile = *++argv; 131 | } else if (strcmp("-i", *argv) == 0 && argc--) { 132 | /* 133 | * file containing offsets 134 | * that *are* instructions 135 | */ 136 | ifile = *++argv; 137 | } else if (strcmp("-a", *argv) == 0 && argc--) { 138 | /* 139 | * file containing valid A-line (1010) instructions 140 | */ 141 | afile = *++argv; 142 | } else if (strcmp("-b", *argv) == 0 && argc--) { 143 | /* 144 | * file containing offsets of data for which 145 | * a new line of output should be started 146 | */ 147 | bfile = *++argv; 148 | } else if (strcmp("-f", *argv) == 0 && argc--) { 149 | /* 150 | * file containing valid F-line (1111) instructions 151 | */ 152 | ffile = *++argv; 153 | } else if (strcmp("-j", *argv) == 0 && argc--) { 154 | /* 155 | * file containing A-line and F-line 156 | * instructions that cause PC to be changed such 157 | * that it is not necessary for the next word to 158 | * be an instruction 159 | */ 160 | jfile = *++argv; 161 | } else if (strcmp("-n", *argv) == 0 && argc--) { 162 | /* 163 | * file containing offsets that are *not* instructions 164 | */ 165 | nfile = *++argv; 166 | } else if (strcmp("-ns", *argv) == 0 && argc--) { 167 | /* 168 | * file containing offsets that 169 | * are not the *start* of instructions 170 | */ 171 | nsfile = *++argv; 172 | } else if (strcmp("-all", *argv) == 0) 173 | onepass = INCONSISTENT; 174 | else if (strcmp("-allc", *argv) == 0) 175 | onepass = CONSISTENT; 176 | else if (strcmp("-lft", *argv) == 0) 177 | linkfallthrough = 1; 178 | else if (strcmp("-odd", *argv) == 0) 179 | odd = 1; 180 | else if (strcmp("-sp", *argv) == 0) 181 | sp = 1; 182 | else if (strcmp("-l", *argv) == 0) { 183 | lower = 1; 184 | #ifdef DEBUG 185 | } else if (strncmp("-d", *argv, 2) == 0) { 186 | extern int debug; 187 | 188 | if (isdigit(argv[0][2])) 189 | debug = atoi(&argv[0][2]); 190 | #endif 191 | #ifndef NOBAD 192 | } else if (strcmp("-bad", *argv) == 0) { 193 | dobad = 1; 194 | #endif 195 | } else if (strcmp("-s", *argv) == 0 && argc--) { 196 | minlen = atoi(*++argv); 197 | if (minlen < 2) 198 | minlen = 2; 199 | } else if (strcmp("-slenp", *argv) == 0 && argc--) { 200 | slenprint = atoi(*++argv); 201 | if (slenprint < 10) 202 | slenprint = 10; 203 | } else { 204 | fprintf(stderr, "%s: bad option: %s\n", progname, 205 | *argv); 206 | usage(); 207 | } 208 | } 209 | 210 | if (!odd && initialpc & 1) { 211 | fprintf(stderr, "%s: initialpc odd but -odd not specified\n", 212 | progname); 213 | exit(1); 214 | } 215 | 216 | if (!CPU(chip)) 217 | chip |= MC68000; 218 | 219 | if (PMMU(chip) && CPU(chip) < MC68020) { 220 | fprintf(stderr, "%s: bad cpu/coprocessor combination\n", 221 | progname); 222 | exit(1); 223 | } 224 | 225 | if (argc == 0 && onepass) { 226 | infp = stdin; 227 | sfile = "stdin"; 228 | if (setjmp(jmp) == 0) 229 | disassemble(); 230 | } else if (argc == 1 || argc > 1 && !ofile) { 231 | argv--; 232 | while (argc--) { 233 | char *lastslash; 234 | size_t len; 235 | size_t extra; 236 | 237 | if ((infp = fopen(*++argv, "rb")) == NULL) { 238 | perror(*argv); 239 | status++; 240 | continue; 241 | } 242 | 243 | /* 244 | * Determine output filename. 245 | * If unspecified, add ".s" to end of input filename. 246 | */ 247 | if (ofile) 248 | sfile = ofile; 249 | else { 250 | if (lastslash = strrchr(*argv, '/')) 251 | *argv = lastslash + 1; 252 | len = strlen(*argv); 253 | extra = (len > 2 && argv[0][len - 2] == '.' 254 | && argv[0][len - 1] == 'o') ? 0 : 2; 255 | if ((sfile = malloc(len + extra + 1)) == NULL) { 256 | perror(*argv); 257 | status++; 258 | (void)fclose(infp); 259 | continue; 260 | } 261 | strcpy(sfile, *argv); 262 | strcpy(&sfile[len - 2 + extra], ".s"); 263 | } 264 | if ((outfp = fopen(sfile, "w")) == NULL) { 265 | perror(sfile); 266 | status++; 267 | (void)fclose(infp); 268 | continue; 269 | } 270 | if (setjmp(jmp) == 0) 271 | disassemble(); 272 | (void)fclose(infp); 273 | (void)fclose(outfp); 274 | if (!ofile) 275 | free(sfile); 276 | } 277 | } else 278 | usage(); 279 | 280 | exit(status); 281 | } 282 | -------------------------------------------------------------------------------- /dis.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * This file contains function prototypes, global variable declarations, 20 | * and #defined masks and macros for manipulating the flags member 21 | * of a struct inst. 22 | */ 23 | 24 | #ifndef DIS_H 25 | #define DIS_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | /* Eight bits here */ 32 | #define BYTE 0x00 33 | #define WORD 0x01 34 | #define LONGWORD 0x02 35 | #define DOUBLELONGWORD 0x04 36 | #define SINGLE 0x08 37 | #define DOUBLE 0x10 38 | #define EXTENDED 0x20 39 | #define PACKED 0x40 40 | #define PWORD WORD 41 | #define PLONGWORD LONGWORD 42 | #define PDOUBLELONGWORD DOUBLELONGWORD 43 | #define PSINGLE SINGLE 44 | #define PDOUBLE DOUBLE 45 | #define PEXTENDED EXTENDED 46 | #define PPACKED PACKED 47 | #define PBYTE 0x80 48 | #define size2f(s) ((s) == BYTE ? PBYTE : (s)) 49 | #define ISINTEGRAL(s) ((s) <= DOUBLELONGWORD) 50 | 51 | /* Four bits here */ 52 | #define MAXOPSMASK 15 /* 4 bits => 1111 base 2 */ 53 | #define f2sharps(f) (((f) >> 8) & MAXOPSMASK) 54 | #define sharp2f(arg) (1 << (8 + (arg) - 1)) 55 | 56 | #define f2ops(f) ((f) >> 12) 57 | #define ops2f(n) ((n) << 12) 58 | 59 | #define FROM 0 60 | #define TO 1 61 | 62 | #define MC68000 0x0001 63 | #define MC68008 0x0002 64 | #define MC68010 0x0004 65 | #define MC68020 0x0008 66 | #define MC68030 0x0010 67 | #define MC68040 0x0020 68 | #define CPU(m) ((m) & 0x3f) 69 | 70 | #define MC68851 0x8000 71 | #define PMMU(m) ((m) & MC68851) 72 | #define MC68881 0x4000 73 | #define MC68882 0x2000 74 | #define FPU(m) ((m) & (MC68881 | MC68882)) 75 | 76 | #define FIRSTPASS 1 77 | #define LASTPASS 2 78 | #define DEBUGPASS 3 79 | #define DCLABELSPASS 4 80 | 81 | #define INCONSISTENT 1 82 | #define CONSISTENT 2 83 | 84 | #if CHAR_BIT == 8 85 | #if UCHAR_MAX == 255U 86 | typedef unsigned char u8bit_t; 87 | #endif 88 | #else 89 | typedef no_8_bit_type u8bit_t; 90 | #endif 91 | #if USHRT_MAX == 65535U 92 | typedef unsigned short u16bit_t; 93 | #else 94 | typedef no_16_bit_type u16bit_t; 95 | #endif 96 | #if UINT_MAX == 4294967295U 97 | typedef unsigned int u32bit_t; 98 | typedef int s32bit_t; 99 | #else 100 | typedef no_32_bit_type u32bit_t; 101 | #endif 102 | 103 | typedef u16bit_t word_t; 104 | typedef s32bit_t addr_t; 105 | 106 | extern FILE *infp; 107 | extern FILE *outfp; 108 | extern char *cc[]; 109 | extern char *bitd[]; 110 | extern char *bitf[]; 111 | extern char buf1[]; 112 | extern char buf2[]; 113 | extern char buf3[]; 114 | 115 | extern int pass; 116 | extern int valid; 117 | 118 | extern addr_t pc; 119 | extern addr_t ppc; 120 | extern addr_t initialpc; 121 | extern int chip; 122 | extern int lower; 123 | extern int minlen; 124 | extern int onepass; 125 | extern int sp; 126 | extern int odd; 127 | extern int linkfallthrough; 128 | extern size_t slenprint; 129 | #ifndef NOBAD 130 | extern int dobad; 131 | #endif 132 | extern char *afile; 133 | extern char *bfile; 134 | extern char *ffile; 135 | extern char *ifile; 136 | extern char *jfile; 137 | extern char *nfile; 138 | extern char *nsfile; 139 | 140 | extern jmp_buf jmp; 141 | extern char *sfile; 142 | 143 | extern long curoffset; 144 | extern short flags; 145 | extern addr_t required[3]; 146 | extern int pcrelative; 147 | 148 | struct inst { 149 | short size; 150 | short flags; 151 | addr_t *required; 152 | short labelnum; 153 | }; 154 | 155 | extern struct inst *insts; 156 | extern addr_t maxoffset; 157 | 158 | /* 159 | * The lowest 2 bits of flags hold the number of dependencies 160 | * so we start with 4 below. 161 | */ 162 | #define ISBRA 0x0004 163 | #define ISBSR 0x0008 164 | #define ISBRcc 0x0010 165 | #define ISDBcc 0x0020 166 | #define ISRTS 0x0040 167 | #define ISJMP 0x0080 168 | #define ISJSR 0x0100 169 | #define ISLINK 0x0200 170 | #define ISUNLK 0x0400 171 | #define ISLABEL 0x0800 172 | #define ISGOOD 0x1000 173 | #define ISFPU 0x2000 174 | 175 | /* 176 | * These are overloaded for floating-point constants. 177 | */ 178 | #define L_ISSINGLE ISBRA 179 | #define L_ISDOUBLE ISBSR 180 | #define L_ISEXTENDED ISBRcc 181 | #define L_ISPACKED ISDBcc 182 | 183 | extern addr_t nextlabel(addr_t); 184 | extern void disassemble(void); 185 | 186 | struct cp { 187 | char *prefix; 188 | void (*gen)(word_t); 189 | char *(*cc)(unsigned int); 190 | }; 191 | 192 | extern struct cp coproc[]; 193 | 194 | /* pgen.c functions */ 195 | extern void pgen(word_t); 196 | extern char *pcc(unsigned); 197 | 198 | /* fgen.c functions */ 199 | extern void fgen(word_t); 200 | extern char *fcc(unsigned); 201 | extern int flis2type(int); 202 | extern int ftype2lis(int); 203 | extern size_t fsizeof(int); 204 | 205 | /* inst2.c functions */ 206 | extern void bit_dynamic(word_t); 207 | extern void bit_static(word_t); 208 | extern void biti_reg(const char *, int, const char *); 209 | extern void biti_size(const char *, word_t); 210 | extern void cmp2_chk2(word_t); 211 | extern void movep(word_t); 212 | extern void cas(word_t); 213 | extern void cas2(word_t); 214 | extern void moves(word_t); 215 | extern void move(word_t, int); 216 | extern void misc_size(const char *, word_t); 217 | extern void misc_ea(const char *, word_t, int); 218 | extern void chk(word_t); 219 | extern void lea(word_t); 220 | extern void link(word_t, int); 221 | extern void unlk(word_t); 222 | extern void swap(word_t); 223 | extern void bkpt(word_t); 224 | extern void trap(word_t); 225 | extern void stop_rtd(const char *); 226 | extern void movec(int); 227 | extern void ext(word_t); 228 | extern void movereg(word_t, const char *, int); 229 | extern void moveusp(word_t, int); 230 | extern void movem(word_t, int); 231 | extern void dbcc(word_t); 232 | extern void trapcc(word_t); 233 | extern void scc(word_t); 234 | extern void pack_unpk(const char *, word_t); 235 | extern void addq_subq(word_t); 236 | extern void op1(const char *, word_t); 237 | extern void op2(const char *, word_t); 238 | extern void op2long(const char *, word_t); 239 | extern void opa(const char *, word_t); 240 | extern void opx(const char *, word_t, int, int); 241 | extern void exg(word_t, char, char); 242 | extern void bitfield(word_t); 243 | extern void getshiftname(char *, int, int); 244 | extern void shift(word_t); 245 | extern void cptrapcc(struct cp *, word_t); 246 | extern void cpdbcc(struct cp *, word_t); 247 | extern void cpbcc(struct cp *, word_t); 248 | extern void cpscc(struct cp *, word_t); 249 | extern void cpsave(const char *, word_t); 250 | extern void cprestore(const char *, word_t); 251 | 252 | /* inst1.c functions */ 253 | extern void bit_movep_immediate(word_t); 254 | extern void movebyte(word_t); 255 | extern void movelong(word_t); 256 | extern void moveword(word_t); 257 | extern void misc(word_t); 258 | extern void addq_subq_scc_dbcc_trapcc(word_t); 259 | extern int bcc_bsr(word_t); 260 | extern void moveq(word_t); 261 | extern void or_div_sbcd(word_t); 262 | extern void sub_subx(word_t); 263 | extern void aline(word_t); 264 | extern void cmp_eor(word_t); 265 | extern void and_mul_abcd_exg(word_t); 266 | extern void add_addx(word_t); 267 | extern void shift_rotate_bitfield(word_t); 268 | extern void coprocessor(word_t); 269 | extern void fline(word_t); 270 | extern void unimplemented(word_t); 271 | 272 | /* utils.c functions */ 273 | extern int immsprintf(char *, long); 274 | extern long signextend(long, int); 275 | extern int nextword(word_t *); 276 | extern long getval(int, int *); 277 | extern char *Areg(int); 278 | extern void Areg2(char [], char, int); 279 | extern int fponit(u32bit_t *, int, char *); 280 | extern int getea(char *, word_t, word_t, int); 281 | extern void instprint(int, const char *, ...); 282 | extern char *regbyte(char *, unsigned char, char *, int); 283 | extern void revbits(unsigned long *, size_t); 284 | 285 | #endif /* DIS_H */ 286 | -------------------------------------------------------------------------------- /pgen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * MC68851 PMMU support. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "dis.h" 26 | #include "addr.h" 27 | 28 | static char *pccs[] = { 29 | "BS", "BC", "LS", "LC", "SS", "SC", "AS", "AC", 30 | "WS", "WC", "IS", "IC", "GS", "GC", "CS", "CC" 31 | }; 32 | #define NPCCS (sizeof pccs / sizeof pccs[0]) 33 | 34 | char * 35 | pcc(unsigned condition) 36 | { 37 | return (condition < NPCCS) ? pccs[condition] : NULL; 38 | } 39 | 40 | static int 41 | getfc(char *s, unsigned value) 42 | { 43 | if (value == 0) 44 | strcpy(s, "SFC"); 45 | else if (value == 1) 46 | strcpy(s, "DFC"); 47 | else if (value & 0x0010) { 48 | if (!PMMU(chip) && (value & 8)) 49 | return -1; 50 | sprintf(s, "FC%d", value & 0xf); 51 | } else if (value & 8) 52 | sprintf(s, "D%d", value & 0x7); 53 | else 54 | return -1; 55 | 56 | return 0; 57 | } 58 | 59 | static void 60 | pload(word_t inst, unsigned long value) 61 | { 62 | int reg = inst & 7; 63 | int mode = (inst >> 3) & 7; 64 | char sload[7]; 65 | 66 | if (!ISACEA(mode, reg)) 67 | return; 68 | if (value & 0x01de0) 69 | return; 70 | if (getea(buf2, reg, mode, BYTE /* actually unsized */)) 71 | return; 72 | sprintf(sload, "PLOAD%c", value & 0x0200 ? 'R' : 'W'); 73 | if (getfc(buf1, (int)(value & 0x1f)) == -1) 74 | return; 75 | instprint(ops2f(2), sload, buf1, buf2); 76 | 77 | valid = 1; 78 | } 79 | 80 | static void 81 | pvalid(word_t inst, unsigned long value) 82 | { 83 | int reg = inst & 7; 84 | int mode = (inst >> 3) & 7; 85 | 86 | if (!ISACEA(mode, reg)) 87 | return; 88 | 89 | if (value == 0x2800) 90 | strcpy(buf1, "VAL"); 91 | else if ((value & 0xfff8) == 0x2c00) 92 | sprintf(buf1, "A%d", (int)(value & 7)); 93 | else 94 | return; 95 | if (getea(buf2, reg, mode, BYTE /* actually unsized */)) 96 | return; 97 | instprint(ops2f(2), "PVALID", buf1, buf2); 98 | 99 | valid = 1; 100 | } 101 | 102 | static void 103 | pflush(word_t inst, unsigned long value) 104 | { 105 | int eareg = inst & 7; 106 | int eamode = (inst >> 3) & 7; 107 | int mode = (value >> 10) & 7; 108 | int mask = (value >> 5) & 0xf; 109 | char sflush[8]; 110 | 111 | /* 112 | * Should this be enforced when (mode & 2) == 0? 113 | */ 114 | if (!ISACEA(eamode, eareg)) 115 | return; 116 | 117 | if (mode == 1) { 118 | if (value & 0x3ff) 119 | return; 120 | instprint(ops2f(0), "PFLUSHA"); 121 | } else { 122 | if ((mask & 8) && CPU(chip) >= MC68030) 123 | return; 124 | immsprintf(buf2, mask); 125 | if (getfc(buf1, (int)(value & 0x1f)) == -1) 126 | return; 127 | strcpy(sflush, "PFLUSH"); 128 | if (mode & 1) { 129 | if (CPU(chip) >= MC68030) 130 | return; 131 | strcat(sflush, "S"); 132 | } 133 | if (mode & 2) { 134 | if (getea(buf3, eareg, eamode, 135 | BYTE /* actually unsized */)) 136 | return; 137 | instprint(ops2f(3) | sharp2f(2), sflush, buf1, buf2, 138 | buf3); 139 | } else 140 | instprint(ops2f(2) | sharp2f(2), sflush, buf1, buf2); 141 | } 142 | 143 | valid = 1; 144 | } 145 | 146 | static void 147 | pflushr(word_t inst, unsigned long value) 148 | { 149 | int reg = inst & 7; 150 | int mode = (inst >> 3) & 7; 151 | 152 | if (value != 0xa000) 153 | return; 154 | if (!ISMEA(mode, reg)) 155 | return; 156 | 157 | if (getea(buf1, reg, mode, BYTE /* actually unsized */)) 158 | return; 159 | instprint(ops2f(1), "PFLUSHR", buf1); 160 | 161 | valid = 1; 162 | } 163 | 164 | static void 165 | pmove(word_t inst, unsigned long value) 166 | { 167 | int reg = inst & 7; 168 | int mode = (inst >> 3) & 7; 169 | int pmmureg = (value >> 10) & 7; 170 | int size; 171 | char *cp1, *cp2; 172 | int fd = value & 0x0100; 173 | 174 | /* 175 | * Sizes: 176 | * 177 | * MC68851 178 | * ------- 179 | * Double long: CRP, SRP, DRP 180 | * Long: TC 181 | * Word: BAC, BAD, AC, PSR, PCSR 182 | * Byte: CAL, VAL, SCC 183 | * 184 | * MC68030 185 | * ------- 186 | * Double long: CRP, SRP 187 | * Long: TC, TT0, TT1 188 | * Word: MMUSR 189 | */ 190 | 191 | strcpy(buf3, "PMOVE"); 192 | if (CPU(chip) >= MC68030) { 193 | if (!ISACEA(mode, reg)) 194 | return; 195 | 196 | switch ((value >> 13) & 7) { 197 | case 0: 198 | if ((value & 0x18ff) != 0x0800) 199 | return; 200 | sprintf(buf1, "TT%d", pmmureg & 1); 201 | break; 202 | case 2: 203 | if (value & 0x10ff) 204 | return; 205 | switch (pmmureg) { 206 | case 0: 207 | strcpy(buf1, "TC"); 208 | break; 209 | case 2: 210 | strcpy(buf1, "SRP"); 211 | break; 212 | case 3: 213 | strcpy(buf1, "CRP"); 214 | break; 215 | default: 216 | return; 217 | } 218 | break; 219 | case 3: 220 | if (value & 0x1dff) 221 | return; 222 | strcpy(buf1, "MMUSR"); 223 | break; 224 | default: 225 | return; 226 | } 227 | if (fd) { 228 | if (value & 0x0200) 229 | return; 230 | strcat(buf3, "FD"); 231 | } 232 | } else { 233 | /* MC68851 */ 234 | if ((value & 0x2000) == 0) { 235 | if (pmmureg >= 1 && pmmureg <= 3 236 | && (ISDATA(mode) || ISDIRECT(mode))) 237 | return; 238 | 239 | switch (pmmureg) { 240 | case 0: 241 | strcpy(buf1, "TC"); 242 | size = LONGWORD; 243 | break; 244 | case 1: 245 | strcpy(buf1, "DRP"); 246 | size = DOUBLELONGWORD; 247 | break; 248 | case 2: 249 | strcpy(buf1, "SRP"); 250 | size = DOUBLELONGWORD; 251 | break; 252 | case 3: 253 | strcpy(buf1, "CRP"); 254 | size = DOUBLELONGWORD; 255 | break; 256 | case 4: 257 | strcpy(buf1, "CAL"); 258 | size = BYTE; 259 | break; 260 | case 5: 261 | strcpy(buf1, "VAL"); 262 | size = BYTE; 263 | break; 264 | case 6: 265 | strcpy(buf1, "SCC"); 266 | size = BYTE; 267 | break; 268 | case 7: 269 | strcpy(buf1, "AC"); 270 | size = WORD; 271 | break; 272 | } 273 | } else { 274 | int num = (value >> 2) & 7; 275 | 276 | if (!ISAEA(mode, reg)) 277 | return; 278 | 279 | size = WORD; 280 | switch (pmmureg) { 281 | case 0: 282 | if (num) 283 | return; 284 | strcpy(buf1, "PSR"); 285 | break; 286 | case 1: 287 | if (num || (value & 0x0200) == 0) 288 | return; 289 | strcpy(buf1, "PCSR"); 290 | break; 291 | case 4: 292 | sprintf(buf1, "BAD%d", num); 293 | break; 294 | case 5: 295 | sprintf(buf1, "BAC%d", num); 296 | break; 297 | default: 298 | return; 299 | } 300 | } 301 | } 302 | if (getea(buf2, reg, mode, size)) 303 | return; 304 | if (value & 0x0200) { 305 | cp1 = buf1; 306 | cp2 = buf2; 307 | } else { 308 | cp1 = buf2; 309 | cp2 = buf1; 310 | } 311 | 312 | instprint(ops2f(2), buf3, cp1, cp2); 313 | 314 | valid = 1; 315 | } 316 | 317 | static void 318 | ptest(word_t inst, unsigned long value) 319 | { 320 | int reg = inst & 7; 321 | int mode = (inst >> 3) & 7; 322 | int level = (value >> 10) & 7; 323 | int areg = (value >> 5) & 7; 324 | char sareg[3]; 325 | char stest[7]; 326 | 327 | if (!ISACEA(mode, reg)) 328 | return; 329 | if (getea(buf2, reg, mode, BYTE /* actually unsized */)) 330 | return; 331 | sprintf(stest, "PTEST%c", value & 0x0200 ? 'R' : 'W'); 332 | if (getfc(buf1, (int)(value & 0x1f)) == -1) 333 | return; 334 | immsprintf(buf3, level); 335 | if (value & 0x0100) { 336 | sprintf(sareg, "A%d", areg); 337 | instprint(ops2f(4) | sharp2f(3), stest, buf1, buf2, buf3, 338 | sareg); 339 | } else 340 | instprint(ops2f(3) | sharp2f(3), stest, buf1, buf2, buf3); 341 | 342 | valid = 1; 343 | } 344 | 345 | void 346 | pgen(word_t inst) 347 | { 348 | unsigned long value; 349 | int failure; 350 | 351 | value = getval(WORD, &failure) & 0xffff; 352 | if (failure) 353 | return; 354 | 355 | switch ((value >> 13) & 7) { 356 | case 0: 357 | if (CPU(chip) >= MC68030) 358 | pmove(inst, value); 359 | break; 360 | case 1: 361 | switch ((value >> 10) & 7) { 362 | case 0: 363 | pload(inst, value); 364 | break; 365 | case 2: /* FALLTHROUGH */ 366 | case 3: 367 | if (PMMU(chip) == MC68851) 368 | pvalid(inst, value); 369 | break; 370 | default: 371 | pflush(inst, value); 372 | break; 373 | } 374 | break; 375 | case 2: /* FALLTHROUGH */ 376 | case 3: 377 | pmove(inst, value); 378 | break; 379 | case 4: 380 | ptest(inst, value); 381 | break; 382 | case 5: 383 | if (PMMU(chip) == MC68851) 384 | pflushr(inst, value); 385 | break; 386 | default: 387 | return; 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /m68kdis.1: -------------------------------------------------------------------------------- 1 | .TH M68KDIS 1 "July 5, 1994" 2 | .SH NAME 3 | m68kdis \- disassemble Motorola 68000 family object code 4 | .SH SYNOPSIS 5 | .LP 6 | m68kdis 7 | \fB[\fP\-\fIddd\fP\fB]\fP 8 | \fB[\fP\-a\ \fIfile\fP\fB]\fP 9 | \fB[\fP\-all[c]\fB]\fP 10 | \fB[\fP\-b\ \fIfile\fP\fB]\fP 11 | \fB[\fP\-bad\fB]\fP 12 | \fB[\fP\-f\ \fIfile\fP\fB]\fP 13 | \fB[\fP\-i\ \fIfile\fP\fB]\fP 14 | \fB[\fP\-j\ \fIfile\fP\fB]\fP 15 | \fB[\fP\-l\fB]\fP 16 | \fB[\fP\-lft\fB]\fP 17 | \fB[\fP\-n\ \fIfile\fP\fB]\fP 18 | \fB[\fP\-ns\ \fIfile\fP\fB]\fP 19 | \fB[\fP\-o\ \fIfile\fP\fB]\fP 20 | \fB[\fP\-odd\fB]\fP 21 | \fB[\fP\-pc\ \fIinitialpc\fP\fB]\fP 22 | \fB[\fP\-s\ \fIlength\fP\fB]\fP 23 | \fB[\fP\-slenp\ \fIlength\fP\fB]\fP 24 | \fB[\fP\-sp\fB]\fP 25 | \fIfile...\fP 26 | .SH DESCRIPTION 27 | .LP 28 | .I m68kdis 29 | is a disassembler for the Motorola 68000 family of cpu chips. 30 | The disassembler attempts to discern between the instruction 31 | and data portions of an object code file. 32 | .LP 33 | .I m68kdis 34 | produces output files much like 35 | .BR cc (1). 36 | When the \fB\-o\fP option is not used, file arguments that end in \.o 37 | have output filenames with \.s substituted for \.o; otherwise, \.s 38 | is simply appended. 39 | .LP 40 | The output consists of five columns: 41 | .IP \(bu 42 | program counter in hexadecimal 43 | .IP \(bu 44 | file contents with each byte displayed as two characters in hexadecimal 45 | .IP \(bu 46 | label (if any) 47 | .IP \(bu 48 | instruction name 49 | .IP \(bu 50 | operands (if any) 51 | .SH OPTIONS 52 | .LP 53 | .IP "\fI\-ddd\fP" 54 | Specifies the chip and coprocessors. 55 | Valid values for 56 | .I ddd 57 | are currently \fI000\fP, \fI008\fP, \fI010\fP, \fI020\fP, 58 | \fI030\fP, \fI851\fP, \fI881\fP, and \fI882\fP. 59 | This option may be repeated as appropriate. 60 | The default is \fI000\fP with no coprocessors. 61 | .IP "\-a\ \fIfile\fP" 62 | Specifies that 63 | .I file 64 | contains lines of the form ``\fIaXXX\ instruction\-string\fP'' which 65 | specify acceptable A-line opcodes. 66 | .I XXX 67 | is in hexadecimal. 68 | .IP \-all[c] 69 | Specifies that only one pass should be made, 70 | outputting the instruction (if any) at each word boundary. 71 | If the 72 | .I c 73 | is included, \fB\-i\fP, \fB\-j\fP, \fB\-n\fP and \fB\-ns\fP options 74 | are also processed, 75 | and another pass is made to ensure consistency between instructions. 76 | .IP "\-b\ \fIfile\fP" 77 | Specifies that 78 | .I file 79 | contains program counter values which are taken as 80 | locations in data to be output on a new line. 81 | The values should be one to a line, and of a form acceptable to 82 | .BR strtoul () 83 | with base equal to 0. 84 | .IP \-bad 85 | Specifies that lines should be printed to standard error that specify 86 | which data caused a potential instruction to be made invalid. 87 | .IP "\-f\ \fIfile\fP" 88 | Specifies that 89 | .I file 90 | contains lines of the form ``\fIfXXX\ instruction\-string\fP'' which 91 | specify acceptable F-line opcodes. 92 | .I XXX 93 | is in hexadecimal. 94 | .IP "\-i\ \fIfile\fP" 95 | Specifies that 96 | .I file 97 | contains program counter values which are, if possible, to be taken as 98 | locations of valid instructions. 99 | The values should be one to a line, and of a form acceptable to 100 | .BR strtoul () 101 | with base equal to 0. 102 | .IP "\-j\ \fIfile\fP" 103 | Specifies that 104 | .I file 105 | contains A-line and F-line opcodes which are unconditional jumps and 106 | therefore do not need to be followed by a valid instruction. 107 | The values should be one to a line, and of a form acceptable to 108 | .BR strtoul () 109 | with base equal to 0. 110 | .IP \-l 111 | Specifies that output should be in lower-case. 112 | (Exception: Label references retain an upper-case ``L''.) 113 | .IP \-lft 114 | Specifies that instructions that ``fall through'' to a LINK instruction 115 | should be considered valid. 116 | By default, these instructions are considered invalid. 117 | .IP "\-n\ \fIfile\fP" 118 | Specifies that 119 | .I file 120 | contains program counter values which are to be taken as 121 | locations of data. 122 | The values should be one to a line, and of a form acceptable to 123 | .BR strtoul () 124 | with base equal to 0. 125 | .IP "\-ns\ \fIfile\fP" 126 | Specifies that 127 | .I file 128 | contains program counter values which are to be taken as 129 | locations at which instructions do not begin. 130 | The words at these locations may, however, be extension words of instructions. 131 | The values should be one to a line, and of a form acceptable to 132 | .BR strtoul () 133 | with base equal to 0. 134 | .IP "\-o\ \fIfile\fP" 135 | Specifies the output file. 136 | Only one file to be disassembled may be given when this option is used. 137 | .IP \-odd 138 | Specifies that instructions may begin at odd offsets. 139 | This can be useful when code to be disassembled is not stripped out of 140 | an object file. 141 | In particular, this option is often needed when disassembling 142 | an intact Macintosh resource fork. 143 | .IP "\-pc\ \fIinitialpc\fP" 144 | Specifies that 145 | .I initialpc 146 | be taken as the program counter value for the start of the object code. 147 | The default is 0. 148 | .IP "\-s\ \fIlength\fP" 149 | Specifies that data contain at least 150 | .I length 151 | consecutive printable characters to be output as a string. 152 | The minimum value for 153 | .I length 154 | is 2; the default is 5. 155 | .IP "\-slenp\ \fIlength\fP" 156 | Specifies that strings should print out no more than 157 | .I length 158 | characters per output line. 159 | The minimum value for 160 | .I length 161 | is 10; the default is 30. 162 | .IP \-sp 163 | Specifies that register A7 should be output as SP, except in MOVEM instructions. 164 | .SH NOTES 165 | .LP 166 | The output is based on Motorola syntax. 167 | .LP 168 | Immediate values are sometimes also output in hexadecimal after an 169 | intervening 170 | 'if t \fC!\fP. 171 | 'if n !. 172 | .LP 173 | The following procedure is used to filter out the data from the instructions: 174 | .IP \(bu 175 | An initial pass is made determining at which file offsets potential 176 | instructions exist and the sizes of those instructions including operands. 177 | .IP \(bu 178 | File offsets specified by the user as being data are processed. 179 | .IP \(bu 180 | File offsets specified by the user as not starting instructions are processed. 181 | .IP \(bu 182 | File offsets specified by the user as being instructions are processed. 183 | .IP \(bu 184 | Potential instructions which reference data as instructions 185 | are changed to data. 186 | (This step is repeated after each of the remaining steps.) 187 | .IP \(bu 188 | LINK instructions which are referenced by BSR and JSR instructions are 189 | accepted as final instructions. 190 | (A final instruction is one that is included in the final output.) 191 | .IP \(bu 192 | Remaining LINK instructions are accepted as final instructions. 193 | .IP \(bu 194 | Branching and jumping instructions that reference final instructions 195 | and are not potential extension words of floating-point instructions 196 | are accepted as final instructions. 197 | .IP \(bu 198 | Remaining branching and jumping that are not extension words of 199 | potential floating-point instructions 200 | and returning instructions are accepted as final instructions. 201 | .IP \(bu 202 | Overlapping instructions are selected by minimizing the amount of data. 203 | .SH BUGS 204 | .LP 205 | .if t You will probably need 16-bit \fCshort\fPs and 32-bit \fCint\fPs. 206 | .if n You will probably need 16-bit \fIshort\fPs and 32-bit \fIint\fPs. 207 | .LP 208 | Since 209 | .I m68kdis 210 | uses the imperfect procedure given in the \fB\s-2NOTES\s+2\fP, 211 | errors may result in the instruction/data determination. 212 | When problems are suspected, the \fB\-bad\fP\fIX\fP option can be used 213 | to determine why instructions get interpreted as data. 214 | You can then use the \fB\-i\fP, \fB\-ns\fP, and \fB\-n\fP options, 215 | as appropriate. 216 | .LP 217 | Two unusual conditions checked for should be mentioned. 218 | Sometimes the decision to designate an instruction as a final instruction 219 | is later contradicted and the instruction is changed to data. 220 | In general, the instruction causing the contradiction should be 221 | regarded as data via the \fB\-ns\fP option. 222 | Also, sometimes it is reported that there is an ``overlap'' at a 223 | certain offset. 224 | This is because 225 | .I m68kdis 226 | is unsure if the best selection of two possible instructions 227 | which overlap each other was made. 228 | A quick inspection of the output at this offset should clear this up. 229 | Messages for these conditions are printed to standard error. 230 | .SH "SEE ALSO 231 | .IP 1. 232 | Motorola: \fIM68000 8/16/32 Bit Microprocessors: 233 | Programmer's Reference Manual\fP\&, 5th ed\., Prentice-Hall, 234 | Englewood Cliffs, NJ, 1986. 235 | .IP 2. 236 | Motorola: \fIM68030: Enhanced 32-Bit Microprocessor 237 | User's Manual\fP\&, 2nd ed\., Prentice-Hall, 238 | Englewood Cliffs, NJ, 1989. 239 | .IP 3. 240 | Motorola: \fIM68851: Paged Memory Management Unit 241 | User's Manual\fP\&, 2nd ed\., Prentice-Hall, 242 | Englewood Cliffs, NJ, 1989. 243 | .IP 4. 244 | Motorola: \fIM68881/MC68882: Floating-Point Coprocessor 245 | User's Manual\fP\&, 2nd ed\., Prentice-Hall, 246 | Englewood Cliffs, NJ, 1989. 247 | .SH AUTHOR 248 | .LP 249 | .nf 250 | Christopher G. Phillips 251 | Christopher_Phillips@pe.utexas.edu 252 | -------------------------------------------------------------------------------- /fgen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * MC68881/MC68882 FPU support. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "dis.h" 26 | #include "addr.h" 27 | 28 | static char *fccs[] = { 29 | "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR", 30 | "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T", 31 | "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE", 32 | "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST" 33 | }; 34 | #define NFCCS (sizeof fccs / sizeof fccs[0]) 35 | 36 | /* 37 | * Here come most of the math functions. 38 | * fmath accounts for those after FSUB. 39 | */ 40 | static char *names[] = { 41 | "FMOVE", "FINT", "FSINH", "FINTRZ", 42 | "FSQRT", NULL, "FLOGNP1", NULL, 43 | "FETOXM1", "FTANH", "FATAN", NULL, 44 | "FASIN", "FATANH", "FSIN", "FTAN", 45 | "FETOX", "FTWOTOX", "FTENTOX", NULL, 46 | "FLOGN", "FLOG10", "FLOG2", NULL, 47 | "FABS", "FCOSH", "FNEG", NULL, 48 | "FACOS", "FCOS", "FGETEXP", "FGETMAN", 49 | "FDIV", "FMOD", "FADD", "FMUL", 50 | "FSGLDIV", "FREM", "FSCALE", "FSGLMUL", 51 | "FSUB" 52 | }; 53 | #define NNAMES (sizeof names / sizeof names[0]) 54 | 55 | char * 56 | fcc(unsigned condition) 57 | { 58 | return (condition < NFCCS) ? fccs[condition] : NULL; 59 | } 60 | 61 | int 62 | flis2type(int is) 63 | { 64 | switch (is) { 65 | case L_ISSINGLE: return SINGLE; 66 | case L_ISDOUBLE: return DOUBLE; 67 | case L_ISEXTENDED: return EXTENDED; 68 | case L_ISPACKED: return PACKED; 69 | default: return -1; 70 | } 71 | } 72 | 73 | int 74 | ftype2lis(int type) 75 | { 76 | switch (type) { 77 | case SINGLE: return L_ISSINGLE; 78 | case DOUBLE: return L_ISDOUBLE; 79 | case EXTENDED: return L_ISEXTENDED; 80 | case PACKED: return L_ISPACKED; 81 | default: return -1; 82 | } 83 | } 84 | 85 | size_t 86 | fsizeof(int type) 87 | { 88 | switch (type) { 89 | case SINGLE: return 2 * sizeof(word_t); 90 | case DOUBLE: return 4 * sizeof(word_t); 91 | case EXTENDED: return 6 * sizeof(word_t); 92 | case PACKED: return 6 * sizeof(word_t); 93 | default: return 0; 94 | } 95 | } 96 | 97 | static int 98 | srcreg2size(int srcreg) 99 | { 100 | switch (srcreg) { 101 | case 0: return LONGWORD; 102 | case 1: return SINGLE; 103 | case 2: return EXTENDED; 104 | case 3: return PACKED; 105 | case 4: return WORD; 106 | case 5: return DOUBLE; 107 | case 6: return BYTE; 108 | default: return -1; 109 | } 110 | } 111 | 112 | static void 113 | fmovefromfp(word_t inst, unsigned long value) 114 | { 115 | int size = (value >> 10) & 7; 116 | int srcreg = (value >> 7) & 7; 117 | int k = value & 0x7f; 118 | int reg = inst & 7; 119 | int mode = (inst >> 3) & 7; 120 | 121 | /* 122 | * destreg and srcreg are switched so the 123 | * call to srcreg2size is correct 124 | * (size is playing the role of destreg) 125 | */ 126 | if ((size = srcreg2size(size)) == -1) { 127 | size = PACKED; 128 | if (k & 0x40) 129 | k |= ~0x7f; /* sign-extend */ 130 | sprintf(buf3, "{#%d}", k); 131 | } else if (size == PACKED) { 132 | if (k & 0xf) 133 | return; 134 | sprintf(buf3, "{D%d}", (int)(k >> 4)); 135 | } else if (k) 136 | return; /* not sure here: manual says k ``should'' be 0 */ 137 | 138 | sprintf(buf1, "FP%d", srcreg); 139 | 140 | #define ISSINGLE(s) ((s) == SINGLE) 141 | if (ISDATA(mode) && !ISINTEGRAL(size) && !ISSINGLE(size) 142 | || !ISADEA(mode, reg)) 143 | return; 144 | #undef ISSINGLE 145 | if (getea(buf2, reg, mode, size)) 146 | return; 147 | if (size == PACKED) 148 | strcat(buf2, buf3); 149 | 150 | instprint(ops2f(2) | size2f(size), "FMOVE", buf1, buf2); 151 | 152 | valid = 1; 153 | } 154 | 155 | static void 156 | fmovelist(word_t inst, unsigned long value) 157 | { 158 | int to_ea = value & 0x2000; 159 | int reg = inst & 7; 160 | int mode = (inst >> 3) & 7; 161 | char *cp1, *cp2; 162 | int nregs; 163 | 164 | if (value & 0x3ff) 165 | return; 166 | if (to_ea && !ISADEA(mode, reg) && !ISDIRECT(mode)) 167 | return; 168 | 169 | cp1 = buf1; 170 | *cp1 = '\0'; 171 | nregs = 0; 172 | if (value & 0x1000) { 173 | cp1 += sprintf(cp1, "FPCR"); 174 | nregs++; 175 | } 176 | if (value & 0x0800) { 177 | if (cp1 != buf1) 178 | *cp1++ = '/'; 179 | cp1 += sprintf(cp1, "FPSR"); 180 | nregs++; 181 | } 182 | if (value & 0x0400) { 183 | if (cp1 != buf1) 184 | *cp1++ = '/'; 185 | cp1 += sprintf(cp1, "FPIAR"); 186 | nregs++; 187 | } 188 | if (cp1 == buf1) 189 | strcpy(cp1, "0"); 190 | 191 | if (ISDATA(mode) && nregs != 1 192 | || ISDIRECT(mode) && nregs != 1 && (value & 0x0400) == 0) 193 | return; 194 | 195 | if (getea(buf2, reg, mode, LONGWORD)) 196 | return; 197 | 198 | if (to_ea) { 199 | cp1 = buf1; 200 | cp2 = buf2; 201 | } else { 202 | cp1 = buf2; 203 | cp2 = buf1; 204 | } 205 | 206 | instprint(ops2f(2) | size2f(LONGWORD), nregs == 1 ? "FMOVE" : "FMOVEM", 207 | cp1, cp2); 208 | 209 | valid = 1; 210 | } 211 | 212 | static void 213 | fmovem(word_t inst, unsigned long value) 214 | { 215 | int to_ea = value & 0x2000; 216 | int eareg = inst & 7; 217 | int eamode = (inst >> 3) & 7; 218 | int mode = (value >> 11) & 3; 219 | unsigned long reglist = value & 0xff; 220 | char *cp1, *cp2; 221 | 222 | if (value & 0x0700) 223 | return; 224 | 225 | if (to_ea) { 226 | if (!ISACEAplusPRE(eamode, eareg)) 227 | return; 228 | } else if (!ISCEAplusPOST(eamode, eareg)) 229 | return; 230 | 231 | /* 232 | * Note that (mode & 2) implies postincrement or control 233 | * addressing mode, otherwise predecrement addressing mode 234 | * 235 | * Not sure what this means though... 236 | */ 237 | if (mode & 1) { 238 | /* 239 | * Dynamic list 240 | */ 241 | if (value & 0x8f) 242 | return; 243 | sprintf(buf1, "D%d", (int)((value >> 4) & 7)); 244 | } else { 245 | /* 246 | * Static list 247 | */ 248 | if (mode & 2) 249 | revbits(®list, 8); 250 | regbyte(buf1, reglist, "FP", 0); 251 | } 252 | 253 | if (getea(buf2, eareg, eamode, EXTENDED)) 254 | return; 255 | 256 | if (to_ea) { 257 | cp1 = buf1; 258 | cp2 = buf2; 259 | } else { 260 | cp1 = buf2; 261 | cp2 = buf1; 262 | } 263 | 264 | instprint(ops2f(2) | size2f(EXTENDED), "FMOVEM", cp1, cp2); 265 | 266 | valid = 1; 267 | } 268 | 269 | static void 270 | fmath(word_t inst, unsigned long value) 271 | { 272 | int reg = inst & 7; 273 | int mode = (inst >> 3) & 7; 274 | int srcreg = (value >> 10) & 7; 275 | int destreg = (value >> 7) & 7; 276 | int cosreg = value & 7; 277 | int use_ea = value & 0x4000; 278 | int size; 279 | size_t name_index = value & 0x7f; 280 | int nops; 281 | char *name = NULL; 282 | 283 | size = EXTENDED; 284 | nops = 2; 285 | if (name_index == 0x3a) { 286 | name = "FTST"; 287 | nops = 1; 288 | sprintf(buf2, "FP%d", destreg); 289 | } else if (name_index >= 0x30 && name_index <= 0x37) { 290 | name = "FSINCOS"; 291 | sprintf(buf2, "FP%d:FP%d", cosreg, destreg /* sine reg */); 292 | } else { 293 | sprintf(buf2, "FP%d", destreg); 294 | if (name_index < NNAMES) 295 | name = names[name_index]; 296 | else if (name_index == 0x38) 297 | name = "FCMP"; 298 | } 299 | if (!name) 300 | return; 301 | 302 | #define ISSINGLE(s) ((s) == SINGLE) 303 | if (use_ea) { 304 | if ((size = srcreg2size(srcreg)) == -1) 305 | return; 306 | if (ISDIRECT(mode) || ISDATA(mode) && !ISINTEGRAL(size) 307 | && !ISSINGLE(size)) 308 | #undef ISSINGLE 309 | return; 310 | if (getea(nops == 1 ? buf2 : buf1, reg, mode, size)) 311 | return; 312 | } else { 313 | if (mode || reg) 314 | return; 315 | if (srcreg == destreg && name_index < 0x20) 316 | nops = 1; 317 | else 318 | sprintf(buf1, "FP%d", srcreg); 319 | } 320 | 321 | if (nops == 1) 322 | instprint(ops2f(1) | size2f(size), name, buf2); 323 | else 324 | instprint(ops2f(2) | size2f(size), name, buf1, buf2); 325 | 326 | valid = 1; 327 | } 328 | 329 | static void 330 | fmovecr(unsigned long value) 331 | { 332 | int reg = (value >> 7) & 7; 333 | int offset = value & 0x7f; 334 | 335 | sprintf(buf2, "FP%d", reg); 336 | 337 | immsprintf(buf1, offset); 338 | switch (offset) { 339 | case 0x00: strcat(buf1, "!PI"); break; 340 | case 0x0b: strcat(buf1, "!Log10(2)"); break; 341 | case 0x0c: strcat(buf1, "!e"); break; 342 | case 0x0d: strcat(buf1, "!Log2(e)"); break; 343 | case 0x0e: strcat(buf1, "!Log10(e)"); break; 344 | case 0x0f: strcat(buf1, "!0.0"); break; 345 | case 0x30: strcat(buf1, "!1n(2)"); break; 346 | case 0x31: strcat(buf1, "!1n(10)"); break; 347 | case 0x32: strcat(buf1, "!10^0"); break; 348 | case 0x33: strcat(buf1, "!10^1"); break; 349 | case 0x34: strcat(buf1, "!10^2"); break; 350 | case 0x35: strcat(buf1, "!10^4"); break; 351 | case 0x36: strcat(buf1, "!10^8"); break; 352 | case 0x37: strcat(buf1, "!10^16"); break; 353 | case 0x38: strcat(buf1, "!10^32"); break; 354 | case 0x39: strcat(buf1, "!10^64"); break; 355 | case 0x3a: strcat(buf1, "!10^128"); break; 356 | case 0x3b: strcat(buf1, "!10^256"); break; 357 | case 0x3c: strcat(buf1, "!10^512"); break; 358 | case 0x3d: strcat(buf1, "!10^1024"); break; 359 | case 0x3e: strcat(buf1, "!10^2048"); break; 360 | case 0x3f: strcat(buf1, "!10^4096"); break; 361 | } 362 | 363 | instprint(ops2f(2), "FMOVECR", buf1, buf2); 364 | 365 | valid = 1; 366 | } 367 | 368 | void 369 | fgen(word_t inst) 370 | { 371 | unsigned long value; 372 | int failure; 373 | 374 | value = getval(WORD, &failure) & 0xffff; 375 | if (failure) 376 | return; 377 | 378 | if ((inst & 0x7f) == 0 && (value & 0xfc00) == 0x5c00) 379 | fmovecr(value); 380 | else 381 | switch ((value >> 13) & 7) { 382 | case 0: /* FALLTHROUGH */ 383 | case 2: 384 | fmath(inst, value); 385 | break; 386 | case 3: 387 | fmovefromfp(inst, value); 388 | break; 389 | case 4: /* FALLTHROUGH */ 390 | case 5: 391 | fmovelist(inst, value); 392 | break; 393 | case 6: /* FALLTHROUGH */ 394 | case 7: 395 | fmovem(inst, value); 396 | break; 397 | default: 398 | return; 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /MAC/rf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #if CHAR_BIT == 8 24 | #if UCHAR_MAX == 255U 25 | typedef unsigned char u8bit_t; 26 | #endif 27 | #else 28 | typedef no_8_bit_type u8bit_t; /* error */ 29 | #endif 30 | #if USHRT_MAX == 65535U 31 | typedef unsigned short u16bit_t; 32 | typedef short s16bit_t; 33 | #else 34 | typedef no_16_bit_type u16bit_t; /* error */ 35 | #endif 36 | #if UINT_MAX == 4294967295U 37 | typedef unsigned int u32bit_t; 38 | typedef int s32bit_t; 39 | #else 40 | typedef no_32_bit_type u32bit_t; /* error */ 41 | #endif 42 | 43 | struct header { 44 | u32bit_t data_offset; /* offset from beginning 45 | of resource file to resource data */ 46 | u32bit_t map_offset; /* offset from beginning 47 | of resource file to resource map */ 48 | u32bit_t data_length; /* Length of resource data */ 49 | u32bit_t map_length; /* Length of resource map */ 50 | }; 51 | #define HEADERSIZE 16 52 | 53 | struct map { 54 | /* 55 | * First there are 22 bytes of zeros: 56 | * 57 | * 16 bytes: reserved for copy of resource header 58 | * 4 bytes: reserved for handle to next resource map to be searched 59 | * 2 bytes: reserved for file reference number 60 | */ 61 | char header[16]; 62 | char handle[4]; 63 | char reference_number[2]; 64 | u16bit_t attributes; /* resource file attributes */ 65 | u16bit_t typelist_offset; /* offset from beginning of 66 | resource map to type list */ 67 | u16bit_t namelist_offset; /* offset from beginning of 68 | resource map to resource 69 | name list */ 70 | }; 71 | #define MAPSIZE 28 72 | 73 | /* 74 | * Resource file attributes 75 | */ 76 | #define MAP_READ_ONLY 0x80 /* set if file is read-only */ 77 | #define MAP_COMPACT 0x40 /* set to compact file on update */ 78 | #define MAP_CHANGED 0x20 /* set to write map on update */ 79 | 80 | struct type { 81 | char type[4]; /* resource type */ 82 | u16bit_t nresources; /* number of resources of this type 83 | in the map (NOT minus 1) */ 84 | u16bit_t offset; /* offset from beginning of type list 85 | to reference list for resources 86 | of this type */ 87 | }; 88 | #define TYPESIZE 8 89 | 90 | struct resource { 91 | u16bit_t ID; /* resource ID */ 92 | s16bit_t name_length_offset; 93 | /* offset from beginning of resource 94 | name list to length of resource name 95 | or -1 if none */ 96 | char attributes; /* resource attributes */ 97 | u32bit_t data_length_offset; 98 | /* offset from beginning of resource 99 | data to length of data for this 100 | resource */ 101 | /* NOTE: length_offset is really only 24 bits */ 102 | }; 103 | #define RESOURCESIZE 12 104 | 105 | /* 106 | * Resource attributes 107 | */ 108 | #define RES_SYS_HEAP 0x40 /* set if read into system heap */ 109 | #define RES_PURGEABLE 0x20 /* set if purgeable */ 110 | #define RES_LOCKED 0x10 /* set if locked */ 111 | #define RES_PROTECTED 0x08 /* set if protected */ 112 | #define RES_PRELOAD 0x04 /* set if to be preloaded */ 113 | #define RES_CHANGED 0x02 /* set if to be written to resource file */ 114 | 115 | /* 116 | * #defines specific to this application 117 | */ 118 | #define FREAD(nbytes, s, fp) if (fread(buf, 1, nbytes, fp) != nbytes) \ 119 | error("read from " s, fp) 120 | #define FREADM(nbytes, s, fp) if (fread(mbuf, 1, nbytes, fp) != nbytes) \ 121 | error("read from " s, fp) 122 | #define FSEEK(offset, s, fp) if (fseek(fp, offset, SEEK_SET) == -1) \ 123 | error("seek to " s, fp) 124 | 125 | #define CVT32(a, index) a = ntohl(*(u32bit_t *)&buf[index]) 126 | #define CVT16(a, index) a = ntohs(*(u16bit_t *)&buf[index]) 127 | 128 | void 129 | od(unsigned char *buf, size_t length) 130 | { 131 | size_t nlines = (length + 15) / 16; 132 | size_t line; 133 | size_t left = length; 134 | short charnum; 135 | 136 | for (line = 0; line < nlines; line++) { 137 | for (charnum = 0; charnum < 16 && left; charnum++, left--) { 138 | if (charnum && (charnum % 2) == 0) 139 | putchar(' '); 140 | printf("%02x", buf[length - left]); 141 | } 142 | putchar('\n'); 143 | } 144 | } 145 | 146 | void 147 | pstr(const unsigned char *s, int length) 148 | { 149 | while (length--) { 150 | if (isprint(*s)) 151 | putchar(*s); 152 | else 153 | printf("\\%0o", *s); 154 | s++; 155 | } 156 | } 157 | 158 | void 159 | error(char *s, FILE *fp) 160 | { 161 | if (fp && ferror(fp)) 162 | perror(s); 163 | else 164 | fprintf(stderr, "Bad file format: %s\n", s); 165 | 166 | exit(1); 167 | } 168 | 169 | void 170 | printrf(FILE *fp) 171 | { 172 | unsigned char buf[BUFSIZ]; 173 | int i; 174 | int j; 175 | long typelist_offset; 176 | long namelist_offset; 177 | long offset; 178 | 179 | struct header header; 180 | char system_use[112]; 181 | char app_data[128]; 182 | struct map map; 183 | u16bit_t ntypes; 184 | struct type type; 185 | struct resource resource; 186 | u8bit_t name_length; 187 | u32bit_t data_length; 188 | unsigned char *mbuf = NULL; 189 | long type_offset; 190 | long resource_offset; 191 | 192 | /* 193 | * Read the header. 194 | */ 195 | FREAD(HEADERSIZE, "header", fp); 196 | CVT32(header.data_offset, 0); 197 | CVT32(header.map_offset, 4); 198 | CVT32(header.data_length, 8); 199 | CVT32(header.map_length, 12); 200 | 201 | /* 202 | * The header is followed by 112 bytes reserved 203 | * for system use and then 128 bytes available 204 | * for application data. 205 | */ 206 | if (fread(system_use, 1, sizeof system_use, fp) != sizeof system_use) 207 | error("system_use", fp); 208 | if (fread(app_data, 1, sizeof app_data, fp) != sizeof app_data) 209 | error("app_data", fp); 210 | 211 | /* 212 | * Read the resource map. 213 | */ 214 | FSEEK(header.map_offset, "map", fp); 215 | FREAD(MAPSIZE, "map", fp); 216 | CVT16(map.attributes, 22); 217 | CVT16(map.typelist_offset, 24); 218 | typelist_offset = header.map_offset + map.typelist_offset; 219 | CVT16(map.namelist_offset, 26); 220 | namelist_offset = header.map_offset + map.namelist_offset; 221 | 222 | printf("Resource file attributes:"); 223 | if (map.attributes == 0) 224 | printf(" none"); 225 | else { 226 | #define DOATTR(attr, string) if (map.attributes & attr) { \ 227 | printf(" " string); \ 228 | map.attributes &= ~attr; \ 229 | } 230 | DOATTR(MAP_READ_ONLY, "read_only") 231 | DOATTR(MAP_COMPACT, "compact") 232 | DOATTR(MAP_CHANGED, "changed") 233 | #undef DOATTR 234 | } 235 | if (map.attributes) 236 | printf(" UNKNOWN"); 237 | printf("\n\n"); 238 | 239 | /* 240 | * The type list contains 241 | * 242 | * 2 bytes: number of resource types in the map minus 1 243 | * 244 | * followed immediately by the types. 245 | */ 246 | FSEEK(typelist_offset, "type list", fp); 247 | FREAD(2, "type list", fp); 248 | CVT16(ntypes, 0); 249 | ntypes++; 250 | 251 | /* 252 | * Read the types. 253 | */ 254 | type_offset = typelist_offset + 2; 255 | for (i = 0; i < ntypes; i++, type_offset += TYPESIZE) { 256 | FSEEK(type_offset, "type", fp); 257 | FREAD(TYPESIZE, "type", fp); 258 | strncpy(type.type, buf, sizeof type.type); 259 | CVT16(type.nresources, 4); 260 | type.nresources++; 261 | CVT16(type.offset, 6); 262 | 263 | if (i) 264 | putchar('\n'); 265 | printf("Resource type: \"%4.4s\"\n", type.type); 266 | printf("\n"); 267 | 268 | /* 269 | * Read the resources. 270 | */ 271 | resource_offset = typelist_offset + type.offset; 272 | for (j = 0; j < type.nresources; j++, 273 | resource_offset += RESOURCESIZE) { 274 | FSEEK(resource_offset, "resource", fp); 275 | FREAD(RESOURCESIZE, "resource", fp); 276 | CVT16(resource.ID, 0); 277 | CVT16(resource.name_length_offset, 2); 278 | resource.attributes = buf[4]; 279 | CVT32(resource.data_length_offset, 4); 280 | resource.data_length_offset &= 0x00ffffff; 281 | 282 | if (j) 283 | putchar('\n'); 284 | printf("ID %d\n", resource.ID); 285 | printf("Attributes:"); 286 | if (resource.attributes == 0) 287 | printf(" none"); 288 | else { 289 | #define DOATTR(attr, string) if (resource.attributes & attr) { \ 290 | printf(" " string); \ 291 | resource.attributes &= ~attr; \ 292 | } 293 | DOATTR(RES_SYS_HEAP, "sys_head") 294 | DOATTR(RES_PURGEABLE, "purgeable") 295 | DOATTR(RES_LOCKED, "locked") 296 | DOATTR(RES_PROTECTED, "protected") 297 | DOATTR(RES_PRELOAD, "preload") 298 | DOATTR(RES_CHANGED, "changed") 299 | #undef DOATTR 300 | } 301 | if (resource.attributes) 302 | printf(" UNKNOWN"); 303 | putchar('\n'); 304 | 305 | if (resource.name_length_offset != -1) { 306 | /* 307 | * Read resource name. 308 | */ 309 | FSEEK(namelist_offset 310 | + resource.name_length_offset, 311 | "resource name", fp); 312 | FREAD(1, "resource name length", fp); 313 | name_length = buf[0]; 314 | FREAD(name_length, "actual resource name", fp); 315 | printf("Name length: %d\n", name_length); 316 | printf("Name: \""); 317 | pstr(buf, name_length); 318 | printf("\"\n"); 319 | } else 320 | printf("No name\n"); 321 | 322 | /* 323 | * Read resource data. 324 | */ 325 | FSEEK(header.data_offset + resource.data_length_offset, 326 | "resource data", fp); 327 | FREAD(4, "resource data length", fp); 328 | CVT32(data_length, 0); 329 | if (data_length 330 | && (mbuf = realloc(mbuf, data_length)) == NULL) { 331 | perror("realloc"); 332 | exit(1); 333 | } 334 | if (data_length) 335 | printf("Bytes %lx to %lx\n", 336 | (long)(header.data_offset 337 | + resource.data_length_offset) + 4, 338 | (long)(data_length + header.data_offset 339 | + resource.data_length_offset + 4 - 1)); 340 | FREADM(data_length, "actual resource data", fp); 341 | od(mbuf, data_length); 342 | } 343 | } 344 | } 345 | 346 | int 347 | main(int argc, char **argv) 348 | { 349 | FILE *fp; 350 | 351 | if (--argc) { 352 | if ((fp = fopen(argv[1], "r")) == NULL) { 353 | perror(argv[1]); 354 | exit(1); 355 | } 356 | } else { 357 | fprintf(stderr, "Usage: %s filename\n", argv[0]); 358 | exit(2); 359 | } 360 | 361 | printrf(fp); 362 | 363 | exit(0); 364 | } 365 | -------------------------------------------------------------------------------- /MAC/mac.0189: -------------------------------------------------------------------------------- 1 | a000 _Open 2 | a001 _Close 3 | a002 _Read 4 | a003 _Write 5 | a004 _Control 6 | a005 _Status 7 | a006 _KillIO 8 | a007 _GetVolInfo 9 | a008 _Create 10 | a009 _Delete 11 | a00a _OpenRF 12 | a00b _Rename 13 | a00c _GetFileInfo 14 | a00d _SetFileInfo 15 | a00e _UnmountVol 16 | a00f _MountVol 17 | a010 _Allocate 18 | a011 _GetEOF 19 | a012 _SetEOF 20 | a013 _FlushVol 21 | a014 _GetVol 22 | a015 _SetVol 23 | a016 _InitQueue 24 | a017 _Eject 25 | a018 _GetFPos 26 | a019 _InitZone 27 | a01b _SetZone 28 | a01c _FreeMem 29 | a01f _DisposPtr 30 | a020 _SetPtrSize 31 | a021 _GetPtrSize 32 | a023 _DisposHandle 33 | a024 _SetHandleSize 34 | a025 _GetHandleSize 35 | a027 _ReallocHandle 36 | a029 _HLock 37 | a02a _HUnlock 38 | a02b _EmptyHandle 39 | a02c _InitApplZone 40 | a02d _SetApplLimit 41 | a02e _BlockMove 42 | a02f _PostEvent 43 | a030 _OSEventAvail 44 | a031 _GetOSEvent 45 | a032 _FlushEvents 46 | a033 _VInstall 47 | a034 _VRemove 48 | a035 _Offline 49 | a036 _MoreMasters 50 | a038 _WriteParam 51 | a039 _ReadDateTime 52 | a03a _SetDateTime 53 | a03b _Delay 54 | a03c _CmpString 55 | a03d _DrvrInstall 56 | a03e _DrvrRemove 57 | a03f _InitUtil 58 | a040 _ResrvMem 59 | a041 _SetFilLock 60 | a042 _RstFilLock 61 | a043 _SetFilType 62 | a044 _SetFSPos 63 | a045 _FlushFile 64 | a047 _SetTrapAddress 65 | a049 _HPurge 66 | a04a _HNoPurge 67 | a04b _SetGrowZone 68 | a04c _CompactMem 69 | a04d _PurgeMem 70 | a04e _AddDrive 71 | a04f _RDrvrInstall 72 | a050 _RelString 73 | a051 _ReadXPRam 74 | a052 _WriteXPRam 75 | a054 _UprString 76 | a055 _StripAddress 77 | a056 _LowerText 78 | a057 _SetAppBase 79 | a058 _InsTime 80 | a059 _RmvTime 81 | a05a _PrimeTime 82 | a05c _MemoryDispatch 83 | a05d _SwapMMUMode 84 | a05e _NMInstall 85 | a05f _NMRemove 86 | a060 _HFSDispatch 87 | a061 _MaxBlock 88 | a062 _PurgeSpace 89 | a063 _MaxApplZone 90 | a064 _MoveHHi 91 | a065 _StackSpace 92 | a066 _NewEmptyHandle 93 | a067 _HSetRBit 94 | a068 _HClrRBit 95 | a069 _HGetState 96 | a06a _HSetState 97 | a06e _SlotManager 98 | a06f _SlotVInstall 99 | a070 _SlotVRemove 100 | a071 _AttachVBL 101 | a072 _DoVBLTask 102 | a075 _DTInstall 103 | a076 _SIntRemove 104 | a077 _CountADBs 105 | a078 _GetIndADB 106 | a079 _GetADBInfo 107 | a07a _SetADBInfo 108 | a07b _ADBReInit 109 | a07c _ADBOp 110 | a07d _GetDefaultStartup 111 | a07e _SetDefaultStartup 112 | a07f _InternalWait 113 | a080 _GetVideoDefault 114 | a081 _SetVideoDefault 115 | a082 _SIntInstall 116 | a083 _SetOSDefault 117 | a084 _GetOSDefault 118 | a08b _CommToolboxDispatch 119 | a08d _DebugUtil 120 | a08f _DeferUsrFn 121 | a090 _SysEnvirons 122 | a097 _UNKNOWN_SPYGLASS 123 | a0dd _PPC 124 | a11a _GetZone 125 | a11d _MaxMem 126 | a11e _NewPtr 127 | a122 _NewHandle 128 | a126 _HandleZone 129 | a128 _RecoverHandle 130 | a12f _PPostEvent 131 | a146 _GetTrapAddress 132 | a148 _PtrZone 133 | a15c _MemoryDispatchA0Result 134 | a191 _Translate24To32 135 | a1ad _Gestalt 136 | a800 _SoundDispatch 137 | a801 _SndDisposeChannel 138 | a802 _SndAddModifier 139 | a803 _SndDoCommand 140 | a804 _SndDoImmediate 141 | a805 _SndPlay 142 | a806 _SndControl 143 | a807 _SndNewChannel 144 | a808 _InitProcMenu 145 | a809 _GetCVariant 146 | a80a _GetWVariant 147 | a80b _PopUpMenuSelect 148 | a80c _RGetResource 149 | a80d _Count1Resources 150 | a80e _Get1IxResource 151 | a810 _Unique1ID 152 | a811 _TESelView 153 | a812 _TEPinScroll 154 | a813 _TEAutoView 155 | a815 _SCSIDispatch 156 | a816 _Pack8 157 | a817 _CopyMask 158 | a818 _FixAtan2 159 | a81a _HOpenResFile 160 | a81b _HCreateResFile 161 | a81c _Count1Types 162 | a81f _Get1Resource 163 | a820 _Get1NamedResource 164 | a821 _MaxSizeRsrc 165 | a823 _AliasDispatch 166 | a827 _UNKNOWN_SPYGLASS 167 | a828 _UNKNOWN_SPYGLASS 168 | a82b _Pack9 169 | a82c _Pack10 170 | a82d _Pack11 171 | a82e _Pack12 172 | a82f _Pack13 173 | a830 _Pack14 174 | a831 _Pack15 175 | a834 _SetFScaleDisable 176 | a835 _FontMetrics 177 | a836 _GetMaskTable 178 | a837 _MeasureText 179 | a838 _CalkMask 180 | a839 _SeedFill 181 | a83a _ZoomWindow 182 | a83b _TrackBox 183 | a83c _TEGetOffset 184 | a83d _TEDispatch 185 | a83e _TEStyleNew 186 | a83f _Long2Fix 187 | a840 _Fix2Long 188 | a841 _Fix2Frac 189 | a842 _Frac2Fix 190 | a843 _Fix2X 191 | a844 _X2Fix 192 | a845 _Frac2X 193 | a846 _X2Frac 194 | a847 _FracCos 195 | a848 _FracSin 196 | a849 _FracSqrt 197 | a84a _FracMul 198 | a84b _FracDiv 199 | a84d _FixDiv 200 | a84e _GetItemCmd 201 | a84f _SetItmCmd 202 | a850 _InitCursor 203 | a851 _SetCursor 204 | a852 _HideCursor 205 | a853 _ShowCursor 206 | a854 _FontDispatch 207 | a855 _ShieldCursor 208 | a856 _ObscureCursor 209 | a858 _BitAnd 210 | a859 _BitXor 211 | a85a _BitNot 212 | a85b _BitOr 213 | a85c _BitShift 214 | a85d _BitTst 215 | a85e _BitSet 216 | a85f _BitClr 217 | a860 _WaitNextEvent 218 | a861 _Random 219 | a862 _ForeColor 220 | a863 _BackColor 221 | a864 _ColorBit 222 | a865 _GetPixel 223 | a866 _StuffHex 224 | a867 _LongMul 225 | a868 _FixMul 226 | a869 _FixRatio 227 | a86a _HiWord 228 | a86b _LoWord 229 | a86c _FixRound 230 | a86d _InitPort 231 | a86e _InitGraf 232 | a86f _OpenPort 233 | a870 _LocalToGlobal 234 | a871 _GlobalToLocal 235 | a872 _GrafDevice 236 | a873 _SetPort 237 | a874 _GetPort 238 | a875 _SetPBits 239 | a876 _PortSize 240 | a877 _MovePortTo 241 | a878 _SetOrigin 242 | a879 _SetClip 243 | a87a _GetClip 244 | a87b _ClipRect 245 | a87c _BackPat 246 | a87d _CloseCPort 247 | a87e _AddPt 248 | a87f _SubPt 249 | a880 _SetPt 250 | a881 _EqualPt 251 | a882 _StdText 252 | a883 _DrawChar 253 | a884 _DrawString 254 | a885 _DrawText 255 | a886 _TextWidth 256 | a887 _TextFont 257 | a888 _TextFace 258 | a889 _TextMode 259 | a88a _TextSize 260 | a88b _GetFontInfo 261 | a88c _StringWidth 262 | a88d _CharWidth 263 | a88e _SpaceExtra 264 | a88f _OSDispatch 265 | a890 _StdLine 266 | a891 _LineTo 267 | a892 _Line 268 | a893 _MoveTo 269 | a894 _Move 270 | a895 _Shutdown 271 | a896 _HidePen 272 | a897 _ShowPen 273 | a898 _GetPenState 274 | a899 _SetPenState 275 | a89a _GetPen 276 | a89b _PenSize 277 | a89c _PenMode 278 | a89d _PenPat 279 | a89e _PenNormal 280 | a8a0 _StdRect 281 | a8a1 _FrameRect 282 | a8a2 _PaintRect 283 | a8a3 _EraseRect 284 | a8a4 _InverRect 285 | a8a5 _FillRect 286 | a8a6 _EqualRect 287 | a8a7 _SetRect 288 | a8a8 _OffsetRect 289 | a8a9 _InsetRect 290 | a8aa _SectRect 291 | a8ab _UnionRect 292 | a8ac _Pt2Rect 293 | a8ad _PtInRect 294 | a8ae _EmptyRect 295 | a8af _StdRRect 296 | a8b0 _FrameRoundRect 297 | a8b1 _PaintRoundRect 298 | a8b2 _EraseRoundRect 299 | a8b3 _InverRoundRect 300 | a8b4 _FillRoundRect 301 | a8b5 _ScriptUtil 302 | a8b6 _StdOval 303 | a8b7 _FrameOval 304 | a8b8 _PaintOval 305 | a8b9 _EraseOval 306 | a8ba _InvertOval 307 | a8bb _FillOval 308 | a8bc _SlopeFromAngle 309 | a8bd _StdArc 310 | a8be _FrameArc 311 | a8bf _PaintArc 312 | a8c0 _EraseArc 313 | a8c1 _InvertArc 314 | a8c2 _FillArc 315 | a8c3 _PtToAngle 316 | a8c4 _AngleFromSlope 317 | a8c5 _StdPoly 318 | a8c6 _FramePoly 319 | a8c7 _PaintPoly 320 | a8c9 _ErasePoly 321 | a8ca _FillPoly 322 | a8cb _OpenPoly 323 | a8cc _ClosePgon 324 | a8cd _KillPoly 325 | a8ce _OffsetPoly 326 | a8cf _PackBits 327 | a8d0 _UnpackBits 328 | a8d1 _StdRgn 329 | a8d2 _FrameRgn 330 | a8d3 _PaintRgn 331 | a8d4 _EraseRgn 332 | a8d5 _InverRgn 333 | a8d6 _FillRgn 334 | a8d7 _BitMapToRegion 335 | a8d8 _NewRgn 336 | a8d9 _DisposRgn 337 | a8da _OpenRgn 338 | a8db _CloseRgn 339 | a8dc _CopyRgn 340 | a8dd _SetEmptyRgn 341 | a8de _SetRecRgn 342 | a8df _SetRectRgn 343 | a8e0 _OffsetRgn 344 | a8e1 _InsetRgn 345 | a8e2 _EmptyRgn 346 | a8e4 _SectRgn 347 | a8e5 _UnionRgn 348 | a8e6 _DiffRgn 349 | a8e7 _XOrRgn 350 | a8e8 _PtInRgn 351 | a8e9 _RectInRgn 352 | a8ea _SetStdProcs 353 | a8eb _StdBits 354 | a8ec _CopyBits 355 | a8ed _StdTxMeas 356 | a8ee _StdGetPic 357 | a8ef _ScrollRect 358 | a8f0 _StdPutPic 359 | a8f1 _StdComment 360 | a8f2 _PicComment 361 | a8f3 _OpenPicture 362 | a8f4 _ClosePicture 363 | a8f5 _KillPicture 364 | a8f6 _DrawPicture 365 | a8f8 _ScalePt 366 | a8f9 _MapPt 367 | a8fa _MapRect 368 | a8fb _MapRgn 369 | a8fc _MapPoly 370 | a8fd _UNKNOWN_KALEIDAGRAPH 371 | a8fe _InitFonts 372 | a8ff _GetFName 373 | a900 _GetFNum 374 | a901 _FMSwapFront 375 | a902 _RealFront 376 | a903 _SetFontLock 377 | a904 _DrawGrowIcon 378 | a905 _DragGrayRgn 379 | a906 _NewString 380 | a907 _SetString 381 | a908 _ShowHide 382 | a909 _CalcVis 383 | a90a _CalcVBehind 384 | a90b _ClipAbove 385 | a90c _PaintOne 386 | a90d _PaintBehind 387 | a90e _SaveOld 388 | a90f _DrawNew 389 | a910 _GetWMgrPort 390 | a911 _CheckUpdate 391 | a912 _InitWindows 392 | a913 _NewWindow 393 | a914 _DisposWindow 394 | a915 _ShowWindow 395 | a916 _HideWindow 396 | a917 _GetWRefCon 397 | a918 _SetWRefCon 398 | a919 _GetWTitle 399 | a91a _SetWTitle 400 | a91b _MoveWindow 401 | a91c _HiliteWindow 402 | a91d _SizeWindow 403 | a91e _TrackGoAway 404 | a91f _SelectWindow 405 | a920 _BringToFront 406 | a921 _SendBehind 407 | a922 _BeginUpdate 408 | a923 _EndUpdate 409 | a924 _FrontWindow 410 | a925 _DragWindow 411 | a926 _DragTheRgn 412 | a927 _InvalRgn 413 | a928 _InvalRect 414 | a929 _ValidRgn 415 | a92a _ValidRect 416 | a92b _GrowWindow 417 | a92c _FindWindow 418 | a92d _CloseWindow 419 | a92e _SetWindowPic 420 | a92f _GetWindowPic 421 | a930 _InitMenus 422 | a931 _NewMenu 423 | a932 _DisposMenu 424 | a933 _AppendMenu 425 | a934 _ClearMenuBar 426 | a935 _InsertMenu 427 | a936 _DeleteMenu 428 | a937 _DrawMenuBar 429 | a938 _HiliteMenu 430 | a939 _EnableItem 431 | a93a _DisableItem 432 | a93b _GetMenuBar 433 | a93c _SetMenuBar 434 | a93d _MenuSelect 435 | a93e _MenuKey 436 | a93f _GetItmIcon 437 | a940 _SetItmIcon 438 | a941 _GetItmStyle 439 | a942 _SetItmStyle 440 | a943 _GetItmMark 441 | a944 _SetItmMark 442 | a945 _CheckItem 443 | a946 _GetItem 444 | a947 _SetItem 445 | a948 _CalcMenuSize 446 | a949 _GetMHandle 447 | a94a _SetMFlash 448 | a94b _PlotIcon 449 | a94c _FlashMenuBar 450 | a94d _AddResMenu 451 | a94e _PinRect 452 | a94f _DeltaPoint 453 | a950 _CountMItems 454 | a951 _InsertResMenu 455 | a952 _DelMenuItem 456 | a953 _UpdtControl 457 | a954 _NewControl 458 | a955 _DisposControl 459 | a956 _KillControls 460 | a957 _ShowControl 461 | a958 _HideControl 462 | a959 _MoveControl 463 | a95a _GetCRefCon 464 | a95b _SetCRefCon 465 | a95c _SizeControl 466 | a95d _HiliteControl 467 | a95e _GetCTitle 468 | a95f _SetCTitle 469 | a960 _GetCtlValue 470 | a961 _GetMinCtl 471 | a962 _GetMaxCtl 472 | a963 _SetCtlValue 473 | a964 _SetMinCtl 474 | a965 _SetMaxCtl 475 | a966 _TestControl 476 | a967 _DragControl 477 | a968 _TrackControl 478 | a969 _DrawControls 479 | a96a _GetCtlAction 480 | a96b _SetCtlAction 481 | a96c _FindControl 482 | a96d _Draw1Control 483 | a96e _Dequeue 484 | a96f _Enqueue 485 | a970 _GetNextEvent 486 | a971 _EventAvail 487 | a972 _GetMouse 488 | a973 _StillDown 489 | a974 _Button 490 | a975 _TickCount 491 | a976 _GetKeys 492 | a977 _WaitMouseUp 493 | a978 _UpdtDialog 494 | a979 _CouldDialog 495 | a97a _FreeDialog 496 | a97b _InitDialogs 497 | a97c _GetNewDialog 498 | a97d _NewDialog 499 | a97e _SelText 500 | a97f _IsDIalogEvent 501 | a980 _DialogSelect 502 | a981 _DrawDialog 503 | a982 _CloseDialog 504 | a983 _DisposDialog 505 | a984 _FindDItem 506 | a985 _Alert 507 | a986 _StopAlert 508 | a987 _NoteAlert 509 | a988 _CautionAlert 510 | a989 _CouldAlert 511 | a98a _FreeAlert 512 | a98b _ParamText 513 | a98c _ErrorSound 514 | a98d _GetDItem 515 | a98e _SetDItem 516 | a98f _SetIText 517 | a990 _GetIText 518 | a991 _ModalDialog 519 | a992 _DetachResource 520 | a993 _SetResPurge 521 | a994 _CurResFile 522 | a995 _InitResources 523 | a996 _RsrcZoneInit 524 | a997 _OpenResFile 525 | a998 _UseResFile 526 | a999 _UpdateResFile 527 | a99a _CloseResFile 528 | a99b _SetResLoad 529 | a99c _CountResources 530 | a99d _GetIndResource 531 | a99e _CountTypes 532 | a99f _GetIndType 533 | a9a0 _GetResource 534 | a9a1 _GetNamedResource 535 | a9a2 _LoadResource 536 | a9a3 _ReleaseResource 537 | a9a4 _HomeResFile 538 | a9a5 _SizeRsc 539 | a9a6 _GetResAttrs 540 | a9a7 _SetResAttrs 541 | a9a8 _GetResInfo 542 | a9a9 _SetResInfo 543 | a9aa _ChangedResource 544 | a9ab _AddResource 545 | a9ad _RmveResource 546 | a9af _ResError 547 | a9b0 _WriteResource 548 | a9b1 _CreateResFile 549 | a9b2 _SystemEvent 550 | a9b3 _SystemClick 551 | a9b4 _SystemTask 552 | a9b5 _SystemMenu 553 | a9b6 _OpenDeskAcc 554 | a9b7 _CloseDeskAcc 555 | a9b8 _GetPattern 556 | a9b9 _GetCursor 557 | a9ba _GetString 558 | a9bb _GetIcon 559 | a9bc _GetPicture 560 | a9bd _GetNewWindow 561 | a9be _GetNewControl 562 | a9bf _GetRMenu 563 | a9c0 _GetNewMBar 564 | a9c1 _UniqueID 565 | a9c2 _SysEdit 566 | a9c3 _KeyTrans 567 | a9c4 _OpemRFPerm 568 | a9c5 _RsrcMapEntry 569 | a9c6 _Secs2Date 570 | a9c7 _Date2Secs 571 | a9c8 _SysBeep 572 | a9c9 _SysError 573 | a9cb _TEGetText 574 | a9cc _TEInit 575 | a9cd _TEDispose 576 | a9ce _TextBox 577 | a9cf _TESetText 578 | a9d0 _TECalText 579 | a9d1 _TESetSelect 580 | a9d2 _TENew 581 | a9d3 _TEUpdate 582 | a9d4 _TEClick 583 | a9d5 _TECopy 584 | a9d6 _TECut 585 | a9d7 _TEDelete 586 | a9d8 _TEActivate 587 | a9d9 _TEDeactivate 588 | a9da _TEIdle 589 | a9db _TEPaste 590 | a9dc _TEKey 591 | a9dd _TEScroll 592 | a9de _TEInsert 593 | a9df _TESetJust 594 | a9e0 _Munger 595 | a9e1 _HandToHand 596 | a9e2 _PtrToXHand 597 | a9e3 _PtrToHand 598 | a9e4 _HandAndHand 599 | a9e5 _InitPack 600 | a9e6 _InitAllPacks 601 | a9e7 _Pack0 602 | a9e8 _Pack1 603 | a9e9 _Pack2 604 | a9ea _Pack3 605 | a9eb _Pack4 606 | a9ec _Pack5 607 | a9ed _Pack6 608 | a9ee _Pack7 609 | a9ef _PtrAndHand 610 | a9f0 _LoadSeg 611 | a9f1 _UnloadSeg 612 | a9f2 _LaunchApplication 613 | a9f3 _Chain 614 | a9f4 _ExitToShell 615 | a9f5 _GetAppParms 616 | a9f6 _GetResFileAttrs 617 | a9f7 _SetResFileAttrs 618 | a9f9 _InfoScrap 619 | a9fa _UnlodeScrap 620 | a9fb _LodeScrap 621 | a9fc _ZeroScrap 622 | a9fd _GetScrap 623 | a9fe _PutScrap 624 | a9ff _UNKNOWN 625 | -------------------------------------------------------------------------------- /inst1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * This file contains the functions called based on the high nibble 20 | * of the potentially valid instruction word. Most of these call 21 | * functions in file inst2.c based on the remaining bits. 22 | */ 23 | 24 | #include 25 | #include 26 | #include "dis.h" 27 | 28 | void 29 | bit_movep_immediate(word_t inst) 30 | { 31 | if (inst == 0x003c) 32 | biti_reg("ORI", BYTE, "CCR"); /* 0000 0000 0011 1100 */ 33 | else if (inst == 0x007c) 34 | biti_reg("ORI", WORD, "SR"); /* 0000 0000 0111 1100 */ 35 | else if ((inst & 0xff00) == 0x0600) 36 | biti_size("ADDI", inst); /* 0000 0110 ---- ---- */ 37 | else if ((inst & 0xf9c0) == 0x00c0) { 38 | if (CPU(chip) >= MC68020) 39 | cmp2_chk2(inst); /* 0000 0--0 11-- ---- */ 40 | } else if ((inst & 0xff00) == 0) 41 | biti_size("ORI", inst); /* 0000 0000 ---- ---- */ 42 | else if (inst == 0x023c) 43 | biti_reg("ANDI", BYTE, "CCR"); /* 0000 0010 0011 1100 */ 44 | else if (inst == 0x027c) 45 | biti_reg("ANDI", WORD, "SR"); /* 0000 0010 0111 1100 */ 46 | else if ((inst & 0xff00) == 0x0200) 47 | biti_size("ANDI", inst); /* 0000 0010 ---- ---- */ 48 | else if ((inst & 0xff00) == 0x0400) 49 | biti_size("SUBI", inst); /* 0000 0100 ---- ---- */ 50 | else if ((inst & 0x0138) == 0x0108) 51 | movep(inst); /* 0000 ---1 --00 1--- */ 52 | else if (inst & 0x0100) 53 | bit_dynamic(inst); /* 0000 ---1 ---- ---- */ 54 | else if ((inst & 0xff00) == 0x0800) 55 | bit_static(inst); /* 0000 1000 ---- ---- */ 56 | else if ((inst & 0xfdff) == 0x0cfc) { 57 | if (CPU(chip) >= MC68020) 58 | cas2(inst); /* 0000 11-0 1111 1100 */ 59 | } else if ((inst & 0xf9c0) == 0x08fc) { 60 | if (CPU(chip) >= MC68020) 61 | cas(inst); /* 0000 1--0 11-- ---- */ 62 | } else if (inst == 0x0a3c) 63 | biti_reg("EORI", BYTE, "CCR"); /* 0000 1010 0011 1100 */ 64 | else if (inst == 0x0a7c) 65 | biti_reg("EORI", WORD, "SR"); /* 0000 1010 0111 1100 */ 66 | else if ((inst & 0xff00) == 0x0a00) 67 | biti_size("EORI", inst); /* 0000 1010 ---- ---- */ 68 | else if ((inst & 0xff00) == 0x0c00) 69 | biti_size("CMPI", inst); /* 0000 1100 ---- ---- */ 70 | else if ((inst & 0x0e00) == 0x0e00) { 71 | if (CPU(chip) >= MC68010) 72 | moves(inst); /* 0000 1110 ---- ---- */ 73 | } 74 | 75 | } 76 | 77 | void 78 | movebyte(word_t inst) 79 | { 80 | move(inst, BYTE); /* 0001 ---- ---- ---- */ 81 | } 82 | 83 | void 84 | movelong(word_t inst) 85 | { 86 | move(inst, LONGWORD); /* 0010 ---- ---- ---- */ 87 | } 88 | 89 | void 90 | moveword(word_t inst) 91 | { 92 | move(inst, WORD); /* 0011 ---- ---- ---- */ 93 | } 94 | 95 | void 96 | misc(word_t inst) 97 | { 98 | if (CPU(chip) >= MC68020 && (inst & 0x0140) == 0x0100 99 | || CPU(chip) < MC68020 && (inst & 0x01c0) == 0x0180) 100 | chk(inst); /* 0100 ---1 ?0-- ---- */ 101 | else if ((inst & 0x0ff8) == 0x09c0) { 102 | if (CPU(chip) >= MC68020) 103 | ext(inst); /* extb /* 0100 1001 1100 0--- */ 104 | } else if ((inst & 0x01c0) == 0x01c0) 105 | lea(inst); /* 0100 ---1 11-- ---- */ 106 | else 107 | switch ((inst >> 8) & 0xf) { 108 | case 0: 109 | if ((inst & 0x00c0) == 0x00c0) 110 | /* 0100 0000 11-- ---- */ movereg(inst, "SR", FROM); 111 | else 112 | /* 0100 0000 ---- ---- */ misc_size("NEGX", inst); 113 | break; 114 | case 2: 115 | if ((inst & 0x00c0) == 0x00c0) { 116 | if (CPU(chip) >= MC68010) 117 | /* 0100 0010 11-- ---- */ movereg(inst, "CCR", FROM); 118 | } else 119 | /* 0100 0010 ---- ---- */ misc_size("CLR", inst); 120 | break; 121 | case 4: 122 | if ((inst & 0x00c0) == 0x00c0) 123 | /* 0100 0100 11-- ---- */ movereg(inst, "CCR", TO); 124 | else 125 | /* 0100 0100 ---- ---- */ misc_size("NEG", inst); 126 | break; 127 | case 6: 128 | if ((inst & 0x00c0) == 0x00c0) 129 | /* 0100 0110 11-- ---- */ movereg(inst, "SR", TO); 130 | else 131 | /* 0100 0110 ---- ---- */ misc_size("NOT", inst); 132 | break; 133 | case 8: 134 | if ((inst & 0x00f8) == 0x0008) { 135 | /* 0100 1000 0000 1--- */ link(inst, LONGWORD); 136 | flags |= ISLINK; 137 | } else if ((inst & 0x00c0) == 0) 138 | /* 0100 1000 00-- ---- */ misc_ea("NBCD", inst, BYTE); 139 | else if ((inst & 0x00f8) == 0x0040) 140 | /* 0100 1000 0100 0--- */ swap(inst); 141 | else if ((inst & 0x00f8) == 0x0048) { 142 | if (CPU(chip) >= MC68010) 143 | /* 0100 1000 0100 1--- */ bkpt(inst); 144 | } else if ((inst & 0x00c0) == 0x0040) 145 | /* 0100 1000 01-- ---- */ misc_ea("PEA", inst, LONGWORD); 146 | else if ((inst & 0x00b8) == 0x0080) 147 | /* 0100 1000 1-00 0--- */ ext(inst); 148 | else if ((inst & 0x0080) == 0x0080) 149 | /* 0100 1000 1--- ---- */ movem(inst, FROM); 150 | break; 151 | case 10: 152 | if (inst == 0x4afc) { 153 | /* 0100 1010 1111 1100 */ instprint(ops2f(0), "ILLEGAL"); 154 | valid = 1; 155 | } else if ((inst & 0x00c0) == 0x00c0) 156 | /* 0100 1010 11-- ---- */ misc_ea("TAS", inst, BYTE); 157 | else 158 | /* 0100 1010 ---- ---- */ misc_size("TST", inst); 159 | break; 160 | case 12: 161 | if ((inst & 0x00c0) == 0) { 162 | if (CPU(chip) >= MC68020) 163 | /* 0100 1100 00-- ---- */ op2long("MUL", inst); 164 | } else if ((inst & 0x00c0) == 0x0040) { 165 | if (CPU(chip) >= MC68020) 166 | /* 0100 1100 01-- ---- */ op2long("DIV", inst); 167 | } else 168 | /* 0100 1100 1--- ---- */ movem(inst, TO); 169 | break; 170 | case 14: 171 | switch ((inst >> 4) & 0xf) { 172 | case 4: 173 | /* 0100 1110 0100 ---- */ trap(inst); 174 | break; 175 | case 5: 176 | if (inst & 8) { 177 | /* 0100 1110 0101 1--- */ unlk(inst); 178 | flags |= ISUNLK; 179 | } else { 180 | /* 0100 1110 0101 0--- */ link(inst, WORD); 181 | flags |= ISLINK; 182 | } 183 | break; 184 | case 6: 185 | if (inst & 8) 186 | /* 0100 1110 0110 1--- */ moveusp(inst, FROM); 187 | else 188 | /* 0100 1110 0110 0--- */ moveusp(inst, TO); 189 | break; 190 | case 7: 191 | switch (inst & 0xf) { 192 | case 0: 193 | /* 0100 1110 0111 0000 */ instprint(ops2f(0), "RESET"); 194 | valid = 1; 195 | break; 196 | case 1: 197 | /* 0100 1110 0111 0001 */ instprint(ops2f(0), "NOP"); 198 | valid = 1; 199 | break; 200 | case 2: 201 | /* 0100 1110 0111 0010 */ stop_rtd("STOP"); 202 | break; 203 | case 3: 204 | /* 0100 1110 0111 0011 */ instprint(ops2f(0), "RTE"); 205 | flags |= ISRTS; 206 | valid = 1; 207 | break; 208 | case 4: 209 | if (CPU(chip) >= MC68010) { 210 | /* 0100 1110 0111 0100 */ stop_rtd("RTD"); 211 | flags |= ISRTS; 212 | valid = 1; 213 | } 214 | break; 215 | case 5: 216 | /* 0100 1110 0111 0101 */ instprint(ops2f(0), "RTS"); 217 | flags |= ISRTS; 218 | valid = 1; 219 | break; 220 | case 6: 221 | /* 0100 1110 0111 0110 */ instprint(ops2f(0), "TRAPV"); 222 | valid = 1; 223 | break; 224 | case 7: 225 | /* 0100 1110 0111 0111 */ instprint(ops2f(0), "RTR"); 226 | flags |= ISRTS; 227 | valid = 1; 228 | break; 229 | default: 230 | if ((inst & 0xe) == 0xa 231 | && CPU(chip) >= MC68010) 232 | /* 0100 1110 0111 101- */ movec(inst & 1); 233 | break; 234 | } 235 | break; 236 | default: 237 | pcrelative = 1; 238 | if (inst & 0x0040) { 239 | /* 0100 1110 11-- ---- */ misc_ea("JMP", inst, 0); 240 | flags |= ISJMP; 241 | } else { 242 | /* 0100 1110 10-- ---- */ misc_ea("JSR", inst, 0); 243 | flags |= ISJSR; 244 | } 245 | pcrelative = 0; 246 | break; 247 | } 248 | break; 249 | #ifdef __alpha 250 | /* Stupid DEC compiler */ 251 | case 15: 252 | break; 253 | #endif 254 | } 255 | } 256 | 257 | void 258 | addq_subq_scc_dbcc_trapcc(word_t inst) 259 | { 260 | if ((inst & 0x00c0) == 0x00c0) { 261 | if ((inst & 0x0038) == 0x0008) { 262 | dbcc(inst); /* 0101 ---- 1100 1--- */ 263 | flags |= ISDBcc; 264 | } else if ((inst & 0x0038) == 0x0038 265 | && 2 <= (inst & 7) && (inst & 7) <= 4) { 266 | if (CPU(chip) >= MC68020) 267 | trapcc(inst); /* 0101 ---- 1111 1--- */ 268 | } else 269 | scc(inst); /* 0101 ---- 11-- ---- */ 270 | } else 271 | addq_subq(inst); /* 0101 ---- ---- ---- */ 272 | } 273 | 274 | int 275 | bcc_bsr(word_t inst) 276 | { 277 | long value; 278 | int condition = (inst >> 8) & 0xf; 279 | char *cp; 280 | addr_t savedpc; 281 | int failure = 0; 282 | 283 | savedpc = pc; 284 | if ((value = signextend(inst & 0xff, 8)) == 0) 285 | value = getval(WORD, &failure); 286 | else if (CPU(chip) >= MC68020 && value == -1) 287 | value = getval(LONGWORD, &failure); 288 | if (failure) 289 | return 0; 290 | if (onepass != INCONSISTENT 291 | && (value < 0 && -value > savedpc - initialpc 292 | || value > 0 && value + savedpc > initialpc + maxoffset 293 | || !odd && value & 1)) 294 | return 0; 295 | 296 | switch (condition) { 297 | case 0: 298 | cp = "RA"; /* 0110 0000 ---- ---- */ 299 | flags |= ISBRA; 300 | break; 301 | case 1: 302 | cp = "SR"; /* 0110 0001 ---- ---- */ 303 | flags |= ISBSR; 304 | break; 305 | default: 306 | cp = cc[condition]; /* 0110 ---- ---- ---- */ 307 | flags |= ISBRcc; 308 | break; 309 | } 310 | sprintf(buf1, "B%s", cp); 311 | 312 | if (pass == FIRSTPASS && onepass != INCONSISTENT) { 313 | required[flags & 3] = value + savedpc; 314 | flags++; 315 | } else if (pass == LASTPASS && value + savedpc >= initialpc 316 | && value + savedpc <= initialpc + maxoffset 317 | && insts[value + savedpc - initialpc].labelnum) 318 | sprintf(buf2, "L%d", 319 | insts[value + savedpc - initialpc].labelnum); 320 | else /* if (pass == DEBUGPASS 321 | || value + savedpc > initialpc + maxoffset) */ 322 | /* immsprintf(buf2, value); */ 323 | sprintf(buf2, "%lx", (long)(value + savedpc)); 324 | instprint(ops2f(1), buf1, buf2); 325 | 326 | return 1; 327 | } 328 | 329 | 330 | void 331 | moveq(word_t inst) /* 0111 ---0 ---- ---- */ 332 | { 333 | int reg = (inst >> 9) & 7; 334 | int value; 335 | 336 | if (inst & 0x0100) 337 | return; 338 | value = signextend(inst & 0xff, 8); 339 | sprintf(buf1, "%d", value); 340 | sprintf(buf2, "D%d", reg); 341 | instprint(ops2f(2) | sharp2f(1), "MOVEQ", buf1, buf2); 342 | 343 | valid = 1; 344 | } 345 | 346 | void 347 | or_div_sbcd(word_t inst) 348 | { 349 | if ((inst & 0x01f0) == 0x0100) 350 | opx("SBCD", inst, 4, 0); /* 1000 ---1 0000 ---- */ 351 | else if ((inst & 0x01f0) == 0x0140) 352 | pack_unpk("PACK", inst); /* 1000 ---1 0100 ---- */ 353 | else if ((inst & 0x01f0) == 0x0180) 354 | pack_unpk("UNPK", inst); /* 1000 ---1 1000 ---- */ 355 | else if ((inst & 0x00c0) == 0x00c0) 356 | op2("DIV", inst); /* 1000 ---- 11-- ---- */ 357 | else 358 | op1("OR", inst); /* 1000 ---- ---- ---- */ 359 | } 360 | 361 | void 362 | sub_subx(word_t inst) 363 | { 364 | if ((inst & 0x00c0) == 0x00c0) 365 | opa("SUBA", inst); /* 1001 ---- 11-- ---- */ 366 | else if ((inst & 0x0130) == 0x0100) 367 | opx("SUBX", inst, 4, 1); /* 1001 ---1 --00 ---- */ 368 | else 369 | op1("SUB", inst); /* 1001 ---- ---- ---- */ 370 | } 371 | 372 | void 373 | unimplemented(word_t inst) 374 | { 375 | instprint(ops2f(0), "UNIMPLEMENTED"); /* 1010 ---- ---- ---- */ 376 | } 377 | 378 | void 379 | cmp_eor(word_t inst) 380 | { 381 | if ((inst & 0x00c0) == 0x00c0) 382 | opa("CMPA", inst); /* 1011 ---- 11-- ---- */ 383 | else if ((inst & 0x0100) == 0) 384 | op1("CMP", inst); /* 1011 ---0 ---- ---- */ 385 | else if ((inst & 0x0038) == 8) 386 | opx("CMPM", inst, 3, 1); /* 1011 ---1 --00 1--- */ 387 | else 388 | op1("EOR", inst); /* 1011 ---1 ---- ---- */ 389 | } 390 | 391 | void 392 | and_mul_abcd_exg(word_t inst) 393 | { 394 | if ((inst & 0x00c0) == 0x00c0) 395 | op2("MUL", inst); /* 1100 ---- 11-- ---- */ 396 | else if ((inst & 0x01f0) == 0x0100) 397 | opx("ABCD", inst, 4, 0); /* 1100 ---1 0000 ---- */ 398 | else 399 | switch (inst & 0x01f8) { 400 | case 0x0140: 401 | exg(inst, 'D', 'D'); /* 1100 ---1 0100 0--- */ 402 | break; 403 | case 0x0148: 404 | exg(inst, 'A', 'A'); /* 1100 ---1 0100 1--- */ 405 | break; 406 | case 0x0188: 407 | exg(inst, 'D', 'A'); /* 1100 ---1 1000 1--- */ 408 | break; 409 | default: 410 | op1("AND", inst); /* 1100 ---- ---- ---- */ 411 | } 412 | } 413 | 414 | void 415 | add_addx(word_t inst) 416 | { 417 | if ((inst & 0x00c0) == 0x00c0) 418 | opa("ADDA", inst); /* 1101 ---- 11-- ---- */ 419 | else if ((inst & 0x0130) == 0x0100) 420 | opx("ADDX", inst, 4, 1); /* 1101 ---1 --00 ---- */ 421 | else 422 | op1("ADD", inst); /* 1101 ---- ---- ---- */ 423 | } 424 | 425 | void 426 | shift_rotate_bitfield(word_t inst) 427 | { 428 | if ((inst & 0x08c0) == 0x08c0) { 429 | if (CPU(chip) >= MC68020) 430 | bitfield(inst); /* 1110 1--- 11-- ---- */ 431 | } else 432 | shift(inst); /* 1110 ---- ---- ---- */ 433 | } 434 | 435 | /* 436 | * Coprocessor support. Currently only the PMMU and FPU available. 437 | */ 438 | 439 | struct cp coproc[] = { 440 | { "P", pgen, pcc }, 441 | { "F", fgen, fcc }, 442 | }; 443 | #define NCP (sizeof coproc / sizeof coproc[0]) 444 | 445 | void 446 | coprocessor(word_t inst) 447 | { 448 | int num = (inst >> 9) & 7; 449 | struct cp *cpptr; 450 | const char *prefix; 451 | 452 | if (num >= NCP || !coproc[num].prefix) 453 | return; 454 | 455 | cpptr = &coproc[num]; 456 | prefix = cpptr->prefix; 457 | 458 | if (num == 0 && PMMU(chip) != MC68851 459 | && (CPU(chip) < MC68030 || ((inst >> 6) & 7))) 460 | return; 461 | if (num == 1 && !FPU(chip)) 462 | return; 463 | 464 | switch ((inst >> 6) & 7) { 465 | case 0: 466 | (*cpptr->gen)(inst); /* 1111 num0 00-- ---- */ 467 | if (valid && num == 1) 468 | flags |= ISFPU; 469 | break; 470 | case 1: 471 | if ((inst & 0x0038) == 0x0038) 472 | cptrapcc(cpptr, inst); /* 1111 num0 0111 1--- */ 473 | else if ((inst & 0x0038) == 0x0008) 474 | cpdbcc(cpptr, inst); /* 1111 num0 0100 1--- */ 475 | else 476 | cpscc(cpptr, inst); /* 1111 num0 01-- ---- */ 477 | break; 478 | case 2: 479 | case 3: 480 | cpbcc(cpptr, inst); /* 1111 num0 1--- ---- */ 481 | break; 482 | case 4: 483 | cpsave(prefix, inst); /* 1111 num1 00-- ---- */ 484 | break; 485 | case 5: 486 | cprestore(prefix, inst); /* 1111 num1 01-- ---- */ 487 | break; 488 | } 489 | } 490 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `m68kdis` 2 | 3 | ## Prelude 4 | _This software was not originally made by me._ It was originally written in 5 | 1994 by one Christopher G. Phillips. AFAICT, it was originally submitted 6 | to Dr. Dobb's Journal [in 1995](http://www.drdobbs.com/cug-new-releases/184403047?pgno=4). 7 | Other than that and some sparse Usenet postings, I have no information on the 8 | original author. 9 | 10 | Unlike most non-commercial assemblers, `m68kdis` can automatically infer code 11 | and data in raw binary images. It is also extremely portable being written in 12 | only ANSI C. If that's not your cup of tea, perhaps bindings can be extracted 13 | for interactive use cases? I might even do it at some point :). 14 | 15 | After thinking I lost my original copy, and not finding the source on Github, 16 | I decided to upload a fresh copy. On Windows 7, it compiles as-is if `gcc` is 17 | installed, and probably works fine with MSVC as well. I personally downloaded 18 | my copy from the [Raine emulator website](https://raine.1emulation.com/download/dev.html), 19 | and commited a copy that was last lightly modified in 2002. 20 | 21 | The manual, converted from `mandoc` into HTML (expect formatting errors), 22 | follows below. 23 | 24 | ## Manual 25 |

M68KDIS

26 | 27 | NAME
28 | SYNOPSIS
29 | DESCRIPTION
30 | OPTIONS
31 | NOTES
32 | BUGS
33 | SEE ALSO
34 | AUTHOR
35 | 36 |
37 | 38 | 39 |

NAME 40 | 41 |

42 | 43 | 44 |

m68kdis − 45 | disassemble Motorola 68000 family object code

46 | 47 |

SYNOPSIS 48 | 49 |

50 | 51 | 52 |

m68kdis 53 | [ddd] 54 | [−a file] [−all[c]] 55 | [−b file] [−bad] 56 | [−f file] 57 | [−i file] 58 | [−j file] [−l] 59 | [−lft] [−n file] 60 | [−ns file] 61 | [−o file] [−odd] 62 | [−pc initialpc] 63 | [−s length] 64 | [−slenp length] 65 | [−sp] file...

66 | 67 |

DESCRIPTION 68 | 69 |

70 | 71 | 72 |

m68kdis 73 | is a disassembler for the Motorola 68000 family of cpu 74 | chips. The disassembler attempts to discern between the 75 | instruction and data portions of an object code file.

76 | 77 |

m68kdis 78 | produces output files much like cc(1). When the 79 | −o option is not used, file arguments that end 80 | in .o have output filenames with .s substituted for .o; 81 | otherwise, .s is simply appended.

82 | 83 |

The output 84 | consists of five columns:

85 | 86 | 88 | 89 | 90 | 94 | 95 | 99 | 100 | 101 | 105 | 106 | 111 | 112 | 113 | 117 | 118 | 122 | 123 | 124 | 128 | 129 | 133 | 134 | 135 | 139 | 140 | 144 |
91 | 92 | 93 |

96 | 97 | 98 |

program counter in hexadecimal

102 | 103 | 104 |

107 | 108 | 109 |

file contents with each byte displayed as two characters 110 | in hexadecimal

114 | 115 | 116 |

119 | 120 | 121 |

label (if any)

125 | 126 | 127 |

130 | 131 | 132 |

instruction name

136 | 137 | 138 |

141 | 142 | 143 |

operands (if any)

145 | 146 |

OPTIONS 147 | 148 |

149 | 150 | 151 | 153 | 154 | 155 | 159 | 160 | 169 |
156 | 157 | 158 |

−ddd

161 | 162 | 163 |

Specifies the chip and 164 | coprocessors. Valid values for ddd are currently 165 | 000, 008, 010, 020, 030, 166 | 851, 881, and 882. This option may be 167 | repeated as appropriate. The default is 000 with no 168 | coprocessors.

170 | 171 |

−a file

172 | 173 |

Specifies that file 174 | contains lines of the form 175 | ‘‘aXXX instruction−string’’ 176 | which specify acceptable A-line opcodes. XXX is in 177 | hexadecimal.

178 | 179 |

−all[c]

180 | 181 |

Specifies that only one pass 182 | should be made, outputting the instruction (if any) at each 183 | word boundary. If the c is included, −i, 184 | −j, −n and −ns 185 | options are also processed, and another pass is made to 186 | ensure consistency between instructions.

187 | 188 |

−b file

189 | 190 |

Specifies that file 191 | contains program counter values which are taken as locations 192 | in data to be output on a new line. The values should be one 193 | to a line, and of a form acceptable to strtoul() with 194 | base equal to 0.

195 | 196 | 198 | 199 | 200 | 204 | 205 | 211 |
201 | 202 | 203 |

−bad

206 | 207 | 208 |

Specifies that lines should be printed to standard error 209 | that specify which data caused a potential instruction to be 210 | made invalid.

212 | 213 |

−f file

214 | 215 |

Specifies that file 216 | contains lines of the form 217 | ‘‘fXXX instruction−string’’ 218 | which specify acceptable F-line opcodes. XXX is in 219 | hexadecimal.

220 | 221 |

−i file

222 | 223 |

Specifies that file 224 | contains program counter values which are, if possible, to 225 | be taken as locations of valid instructions. The values 226 | should be one to a line, and of a form acceptable to 227 | strtoul() with base equal to 0.

228 | 229 |

−j file

230 | 231 |

Specifies that file 232 | contains A-line and F-line opcodes which are unconditional 233 | jumps and therefore do not need to be followed by a valid 234 | instruction. The values should be one to a line, and of a 235 | form acceptable to strtoul() with base equal to 236 | 0.

237 | 238 | 240 | 241 | 242 | 246 | 247 | 253 | 254 | 255 | 259 | 260 | 267 |
243 | 244 | 245 |

−l

248 | 249 | 250 |

Specifies that output should be in lower-case. 251 | (Exception: Label references retain an upper-case 252 | ‘‘L’’.)

256 | 257 | 258 |

−lft

261 | 262 | 263 |

Specifies that instructions that ‘‘fall 264 | through’’ to a LINK instruction should be 265 | considered valid. By default, these instructions are 266 | considered invalid.

268 | 269 |

−n file

270 | 271 |

Specifies that file 272 | contains program counter values which are to be taken as 273 | locations of data. The values should be one to a line, and 274 | of a form acceptable to strtoul() with base equal to 275 | 0.

276 | 277 |

−ns file

278 | 279 |

Specifies that file 280 | contains program counter values which are to be taken as 281 | locations at which instructions do not begin. The words at 282 | these locations may, however, be extension words of 283 | instructions. The values should be one to a line, and of a 284 | form acceptable to strtoul() with base equal to 285 | 0.

286 | 287 |

−o file

288 | 289 |

Specifies the output file. Only 290 | one file to be disassembled may be given when this option is 291 | used.

292 | 293 | 295 | 296 | 297 | 301 | 302 | 310 |
298 | 299 | 300 |

−odd

303 | 304 | 305 |

Specifies that instructions may begin at odd offsets. 306 | This can be useful when code to be disassembled is not 307 | stripped out of an object file. In particular, this option 308 | is often needed when disassembling an intact Macintosh 309 | resource fork.

311 | 312 | 313 |

−pc initialpc

314 | 315 |

Specifies that initialpc 316 | be taken as the program counter value for the start of the 317 | object code. The default is 0.

318 | 319 | 320 |

−s length

321 | 322 |

Specifies that data contain at 323 | least length consecutive printable characters to be 324 | output as a string. The minimum value for length is 325 | 2; the default is 5.

326 | 327 | 328 |

−slenp length

329 | 330 |

Specifies that strings should 331 | print out no more than length characters per output 332 | line. The minimum value for length is 10; the default 333 | is 30.

334 | 335 | 337 | 338 | 339 | 343 | 344 | 349 |
340 | 341 | 342 |

−sp

345 | 346 | 347 |

Specifies that register A7 should be output as SP, 348 | except in MOVEM instructions.

350 | 351 |

NOTES 352 | 353 |

354 | 355 | 356 |

The output is 357 | based on Motorola syntax.

358 | 359 |

Immediate 360 | values are sometimes also output in hexadecimal after an 361 | intervening !.

362 | 363 |

The following 364 | procedure is used to filter out the data from the 365 | instructions:

366 | 367 | 369 | 370 | 371 | 375 | 376 | 383 | 384 | 385 | 389 | 390 | 395 | 396 | 397 | 401 | 402 | 407 | 408 | 409 | 413 | 414 | 419 | 420 | 421 | 425 | 426 | 432 | 433 | 434 | 438 | 439 | 446 | 447 | 448 | 452 | 453 | 458 | 459 | 460 | 464 | 465 | 472 | 473 | 474 | 478 | 479 | 485 | 486 | 487 | 491 | 492 | 497 |
372 | 373 | 374 |

377 | 378 | 379 |

An initial pass is made 380 | determining at which file offsets potential instructions 381 | exist and the sizes of those instructions including 382 | operands.

386 | 387 | 388 |

391 | 392 | 393 |

File offsets specified by the user as being data are 394 | processed.

398 | 399 | 400 |

403 | 404 | 405 |

File offsets specified by the user as not starting 406 | instructions are processed.

410 | 411 | 412 |

415 | 416 | 417 |

File offsets specified by the user as being instructions 418 | are processed.

422 | 423 | 424 |

427 | 428 | 429 |

Potential instructions which reference data as 430 | instructions are changed to data. (This step is repeated 431 | after each of the remaining steps.)

435 | 436 | 437 |

440 | 441 | 442 |

LINK instructions which are referenced by BSR and JSR 443 | instructions are accepted as final instructions. (A final 444 | instruction is one that is included in the final 445 | output.)

449 | 450 | 451 |

454 | 455 | 456 |

Remaining LINK instructions are accepted as final 457 | instructions.

461 | 462 | 463 |

466 | 467 | 468 |

Branching and jumping instructions that reference final 469 | instructions and are not potential extension words of 470 | floating-point instructions are accepted as final 471 | instructions.

475 | 476 | 477 |

480 | 481 | 482 |

Remaining branching and jumping that are not extension 483 | words of potential floating-point instructions and returning 484 | instructions are accepted as final instructions.

488 | 489 | 490 |

493 | 494 | 495 |

Overlapping instructions are selected by minimizing the 496 | amount of data.

498 | 499 |

BUGS 500 | 501 |

502 | 503 | 504 |

You will 505 | probably need 16-bit shorts and 32-bit 506 | ints.

507 | 508 |

Since 509 | m68kdis uses the imperfect procedure given in the 510 | NOTES , errors may result in the 511 | instruction/data determination. When problems are suspected, 512 | the −badX option can be used to 513 | determine why instructions get interpreted as data. You can 514 | then use the −i, −ns, and 515 | −n options, as appropriate.

516 | 517 |

Two unusual 518 | conditions checked for should be mentioned. Sometimes the 519 | decision to designate an instruction as a final instruction 520 | is later contradicted and the instruction is changed to 521 | data. In general, the instruction causing the contradiction 522 | should be regarded as data via the −ns option. 523 | Also, sometimes it is reported that there is an 524 | ‘‘overlap’’ at a certain offset. 525 | This is because m68kdis is unsure if the best 526 | selection of two possible instructions which overlap each 527 | other was made. A quick inspection of the output at this 528 | offset should clear this up. Messages for these conditions 529 | are printed to standard error.

530 | 531 |

SEE ALSO 532 | 533 |

534 | 535 | 536 | 538 | 539 | 540 | 544 | 545 | 551 | 552 | 553 | 557 | 558 | 564 | 565 | 566 | 570 | 571 | 577 | 578 | 579 | 583 | 584 | 590 |
541 | 542 | 543 |

1.

546 | 547 | 548 |

Motorola: M68000 8/16/32 Bit 549 | Microprocessors: Programmer’s Reference Manual, 550 | 5th ed., Prentice-Hall, Englewood Cliffs, NJ, 1986.

554 | 555 | 556 |

2.

559 | 560 | 561 |

Motorola: M68030: Enhanced 32-Bit Microprocessor 562 | User’s Manual, 2nd ed., Prentice-Hall, Englewood 563 | Cliffs, NJ, 1989.

567 | 568 | 569 |

3.

572 | 573 | 574 |

Motorola: M68851: Paged Memory Management Unit 575 | User’s Manual, 2nd ed., Prentice-Hall, Englewood 576 | Cliffs, NJ, 1989.

580 | 581 | 582 |

4.

585 | 586 | 587 |

Motorola: M68881/MC68882: Floating-Point Coprocessor 588 | User’s Manual, 2nd ed., Prentice-Hall, Englewood 589 | Cliffs, NJ, 1989.

591 | 592 |

AUTHOR 593 | 594 |

595 | 596 | 597 |

Christopher G. 598 | Phillips
599 | Christopher_Phillips@pe.utexas.edu

600 |
601 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * Various utility functions including formatting effective addresses, 20 | * reading input (correctly!), and printing are here. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "dis.h" 32 | 33 | /* 34 | * Format immediate constant ``value'' into ``s''. 35 | */ 36 | int 37 | immsprintf(char *s, long value) 38 | { 39 | long absvalue; 40 | char *sign; 41 | 42 | if (pass == FIRSTPASS) 43 | return 0; 44 | 45 | if (value < 0) { 46 | absvalue = -value; 47 | sign = "-$"; 48 | } else { 49 | absvalue = value; 50 | sign = "$"; 51 | } 52 | if (absvalue > 9) 53 | return sprintf(s, "%ld!%s%lx", value, sign, absvalue); 54 | else 55 | return sprintf(s, "%ld", value); 56 | } 57 | 58 | /* 59 | * Sign-extend ``value'' from a ``bits''-bit value to a long. 60 | */ 61 | long 62 | signextend(long value, int bits) 63 | { 64 | switch (bits) { 65 | case 8: 66 | value &= 0xff; 67 | if (value & 0x80) 68 | value |= ~0xffL; 69 | break; 70 | case 16: 71 | value &= 0xffff; 72 | if (value & 0x8000) 73 | value |= ~0xffffL; 74 | break; 75 | case 32: 76 | value &= 0xffffffff; 77 | if (value & 0x80000000) 78 | value |= ~0xffffffffL; 79 | break; 80 | } 81 | 82 | return value; 83 | } 84 | 85 | char instbuf[512]; 86 | int leninstbuf = 0; 87 | 88 | /* 89 | * Read a word from the input file. Put its numerical value in *wp. 90 | */ 91 | int 92 | nextword(word_t *wp) 93 | { 94 | unsigned char c[sizeof(word_t)]; 95 | size_t i; 96 | 97 | if (fread(c, 1, sizeof(word_t), infp) == sizeof(word_t)) { 98 | for (*wp = 0, i = 0; i < sizeof(word_t); i++) 99 | *wp += c[i] << (CHAR_BIT * (sizeof(word_t) - 1 - i)); 100 | pc += sizeof(word_t); 101 | curoffset += sizeof(word_t); 102 | for (i = 0; i < sizeof(word_t); i++) { 103 | sprintf(&instbuf[leninstbuf], "%0*x", sizeof(word_t), 104 | c[i]); 105 | leninstbuf += sizeof(word_t); 106 | } 107 | return 0; 108 | } else 109 | return -1; 110 | } 111 | 112 | /* 113 | * Get a sign-extended value of type ``size'' from the input file. 114 | */ 115 | long 116 | getval(int size, int *failure) 117 | { 118 | word_t extra[2]; 119 | long value; 120 | 121 | if (nextword(&extra[0]) == -1) { 122 | *failure = -1; 123 | return 0; 124 | } 125 | switch (size) { 126 | case BYTE: 127 | #if 0 128 | #ifndef OLD 129 | if (extra[0] & 0xff00) { 130 | *failure = -1; 131 | return 0; 132 | } else 133 | #endif 134 | #endif 135 | value = signextend(extra[0], 8); 136 | break; 137 | case WORD: 138 | value = signextend(extra[0], 16); 139 | break; 140 | case LONGWORD: 141 | if (nextword(&extra[1]) == -1) { 142 | *failure = -1; 143 | return 0; 144 | } 145 | value = signextend(((long)extra[0] << 16) | extra[1], 32); 146 | break; 147 | default: 148 | *failure = -1; 149 | return 0; 150 | break; 151 | } 152 | 153 | *failure = 0; 154 | return value; 155 | } 156 | 157 | /* 158 | * Translate scale bits to a scaling factor. 159 | */ 160 | static int 161 | scale(int s) 162 | { 163 | switch (s) { 164 | case 0: return 1; break; 165 | case 1: return 2; break; 166 | case 2: return 4; break; 167 | case 3: return 8; break; 168 | } 169 | } 170 | 171 | /* 172 | * Format address register ``reg'' taking ``sp'' into account. 173 | */ 174 | char * 175 | Areg(int reg) 176 | { 177 | static char s[2] = "A0"; 178 | 179 | if (sp && reg == 7) 180 | return "SP"; 181 | else { 182 | s[1] = reg + '0'; 183 | return s; 184 | } 185 | } 186 | 187 | /* 188 | * Format register ``reg''. 189 | */ 190 | void 191 | Areg2(char *s, char c, int reg) 192 | { 193 | if (c == 'A') 194 | sprintf(s, "%2.2s", Areg(reg)); 195 | else 196 | sprintf(s, "D%d", reg); 197 | } 198 | 199 | /* 200 | * Extended mode for extension words. 201 | * 202 | * The formatted text goes in ``s''. 203 | * Return 0 for success, negative for failure. 204 | */ 205 | static int 206 | extended(char *s, const char *reg, int size) 207 | { 208 | word_t extra; 209 | addr_t bd; 210 | addr_t od; 211 | addr_t savedpc; 212 | int comma; 213 | int n = 0; 214 | int failure; 215 | char reg2[2]; 216 | 217 | savedpc = pc; 218 | if (nextword(&extra) == -1) 219 | return -1; 220 | if (CPU(chip) < MC68020 || (extra & 0x0100) == 0) { 221 | /* Brief format */ 222 | 223 | long value; 224 | 225 | /* 226 | * Format is as follows: 227 | * 228 | * Bits Name 229 | * 15 Index register type (D/A, 0 if D) 230 | * 12-14 Index register number 231 | * 11 Index size (W/L, 0 if sign-extended word) 232 | * 9-10 Scale (00 = 1, 01 = 2, 10 = 4, 11 = 8) 233 | * 8 Must be 0 234 | * 0-7 Displacement 235 | */ 236 | 237 | if (CPU(chip) >= MC68020) 238 | n += sprintf(s, "("); 239 | value = (long)signextend(extra, 8); 240 | if (/* pcrelative && */ strcmp(reg, "PC") == 0) 241 | value += sizeof(word_t); 242 | n += immsprintf(s + n, value); 243 | n += sprintf(s + n, "%s", (CPU(chip) < MC68020) ? "(" : ","); 244 | Areg2(reg2, (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); 245 | n += sprintf(s + n, "%s,%2.2s.%c", reg, reg2, 246 | (extra & 0x0800) ? 'L' : 'W'); 247 | if (CPU(chip) >= MC68020 && ((extra >> 9) & 3)) 248 | n += sprintf(s + n, "*%d", scale((extra >> 9) & 3)); 249 | n += sprintf(s + n, ")"); 250 | } else { 251 | /* Full format */ 252 | 253 | /* 254 | * Format is as follows: 255 | * 256 | * Bits Name 257 | * 15 Index register type (D/A, 0 if D) 258 | * 12-14 Index register number 259 | * 11 Index size (W/L, 0 if sign-extended word) 260 | * 9-10 Scale (00 = 1, 01 = 2, 10 = 4, 11 = 8) 261 | * 8 Must be 1 262 | * 7 Base suppress (1 if base register suppressed) 263 | * 6 Index suppress (1 if index register suppressed) 264 | * 4-5 Base displacement size (00 = reserved, 265 | 01 = null, 10 = word, 11 = long) 266 | * 3 Must be 0 267 | * 0-2 Index/Indirect selection 268 | 269 | * I/IS combinations: 270 | * 271 | * IS I/IS Operation 272 | * 0 000 No memory indirection 273 | * 0 001 Indirect preindexed with null outer displacement 274 | * 0 010 Indirect preindexed with word od 275 | * 0 011 Indirect preindexed with long od 276 | * 0 101 Indirect postindexed with null od 277 | * 0 110 Indirect postindexed with word od 278 | * 0 111 Indirect postindexed with long od 279 | * 1 000 No memory indirection 280 | * 1 001 Memory indirect with null od 281 | * 1 010 Memory indirect with word od 282 | * 1 011 Memory indirect with long od 283 | */ 284 | 285 | /* 286 | * Get base displacement 287 | */ 288 | switch ((extra >> 4) & 3) { 289 | case 0: 290 | return -1; 291 | break; 292 | case 1: 293 | bd = 0; 294 | break; 295 | case 2: 296 | bd = getval(WORD, &failure); 297 | if (failure) 298 | return failure; 299 | break; 300 | case 3: 301 | bd = getval(LONGWORD, &failure); 302 | if (failure) 303 | return failure; 304 | break; 305 | } 306 | 307 | /* 308 | * Check if collapses to PC-relative 309 | */ 310 | if ((extra & 0x01cf) == 0x0140) { 311 | if (pass == DCLABELSPASS) { 312 | if (bd + savedpc >= initialpc 313 | && bd + savedpc <= initialpc + maxoffset) { 314 | insts[bd + savedpc - initialpc].flags 315 | |= ISLABEL; 316 | if (!insts[ppc - initialpc].size && 317 | insts[ppc - initialpc].flags & ISFPU) 318 | insts[bd + savedpc 319 | - initialpc].flags 320 | |= ftype2lis(size); 321 | } 322 | } else if (pass == FIRSTPASS && pcrelative) { 323 | required[flags & 3] = bd + savedpc; 324 | flags++; 325 | } else if (pass == LASTPASS 326 | && bd + savedpc >= initialpc 327 | && bd + savedpc <= initialpc + maxoffset 328 | && insts[bd + savedpc - initialpc].labelnum) 329 | sprintf(s, "L%d", 330 | insts[bd + savedpc - initialpc].labelnum); 331 | else /* if ((pass == FIRSTPASS || pass == LASTPASS) 332 | && !pcrelative 333 | || pass == DEBUGPASS 334 | || pass == LASTPASS && pcrelative 335 | && bd + savedpc > initialpc + maxoffset) */ { 336 | if (bd) 337 | sprintf(s, "(%ld,PC)!$%lx", bd, 338 | bd + savedpc); 339 | else 340 | sprintf(s, "(PC)!$%lx", savedpc); 341 | } 342 | 343 | return 0; 344 | } 345 | 346 | switch (extra & 3) { 347 | case 0: /* FALLTHROUGH */ 348 | case 1: 349 | od = 0; 350 | break; 351 | case 2: 352 | od = getval(WORD, &failure); 353 | if (failure) 354 | return failure; 355 | break; 356 | case 3: 357 | od = getval(LONGWORD, &failure); 358 | if (failure) 359 | return failure; 360 | break; 361 | } 362 | n += sprintf(s + n, "("); 363 | if (extra & 3) 364 | n += sprintf(s + n, "["); 365 | if (comma = bd) 366 | n += immsprintf(s + n, (long)bd); 367 | if ((extra & 0x0080) == 0) { 368 | /* 369 | * Base suppress is 0. 370 | */ 371 | if (comma) 372 | n += sprintf(s + n, ","); 373 | n += sprintf(s + n, "%s", reg); 374 | comma = 1; 375 | } else if (strcmp(reg, "PC") == 0) { 376 | if (comma) 377 | n += sprintf(s + n, ","); 378 | n += sprintf(s + n, "ZPC"); 379 | comma = 1; 380 | } 381 | if (extra & 4) { 382 | n += sprintf(s + n, "]"); 383 | comma = 1; 384 | } 385 | if ((extra & 0x0040) == 0) { 386 | /* 387 | * Index suppress is 0. 388 | */ 389 | if ((extra & 7) == 4) 390 | return -1; 391 | if (comma) 392 | n += sprintf(s + n, ","); 393 | Areg2(reg2, (extra & 0x8000) ? 'A' : 'D', 394 | (extra >> 12) & 7); 395 | n += sprintf(s + n, "%2.2s.%c", reg2, 396 | (extra & 0x0800) ? 'L' : 'W'); 397 | if ((extra >> 9) & 3) 398 | n += sprintf(s + n, "*%d", 399 | scale((extra >> 9) & 3)); 400 | } else if (extra & 4) 401 | return -1; 402 | if ((extra & 3) && (extra & 4) == 0) { 403 | n += sprintf(s + n, "]"); 404 | comma = 1; 405 | } 406 | if (od) { 407 | if (comma) 408 | n += sprintf(s + n, ","); 409 | n += immsprintf(s + n, (long)od); 410 | } 411 | if (n) { 412 | if (s[n - 1] != '(') 413 | n += sprintf(s + n, ")"); 414 | else { 415 | s[n - 1] = '\0'; 416 | if (--n == 0) 417 | sprintf(s, "0"); 418 | } 419 | } else 420 | sprintf(s, "0"); 421 | } 422 | 423 | return 0; 424 | } 425 | 426 | /* 427 | * The next few functions convert hexadecimal nibble values 428 | * to a floating-point value (and format it). 429 | */ 430 | 431 | #define BIT(p,n) ((p)[(n) / 32] & (1UL << (32 - (n) % 32 - 1))) 432 | 433 | /* 434 | * Is the mantissa zero? 435 | */ 436 | static int 437 | zeromantissa(u32bit_t *p, size_t firstbit, size_t lastbit) 438 | { 439 | size_t bit; 440 | 441 | for (bit = firstbit; bit <= lastbit; bit++) 442 | if (BIT(p, bit)) 443 | return 0; 444 | 445 | return 1; 446 | } 447 | 448 | /* 449 | * Convert the input data in *lwp from bits ``firstbit'' to ``lastbit'' 450 | * into a mantissa. Note that the *highest* bit is considered bit 0 here. 451 | */ 452 | static double 453 | stod(u32bit_t *lwp, size_t firstbit, size_t lastbit) 454 | { 455 | double result = 1.0; 456 | double value = 0.5; 457 | size_t bit; 458 | 459 | for (bit = firstbit; bit <= lastbit && value; bit++) { 460 | if (BIT(lwp, bit)) 461 | result += value; 462 | value /= 2.0; 463 | } 464 | 465 | return result; 466 | } 467 | 468 | /* 469 | * Convert the input data in *longwords into a floating-point value 470 | * of floating-point type ``type'' and place a human-readable version in ``s''. 471 | * Return -1 if NaN or Denormalized, else 0. 472 | */ 473 | int 474 | fpoint(u32bit_t *longwords, int type, char *s) 475 | { 476 | short exponent; 477 | short sign; 478 | short zero; 479 | short maxexp; 480 | short minexp; 481 | size_t firstbit; 482 | size_t lastbit; 483 | int rval = 0; /* return -1 if NaN or Denormalized */ 484 | 485 | /* These are for PACKED */ 486 | short mantissa[17]; 487 | short lastnonzero; 488 | short firstnonzero; 489 | size_t i, n; 490 | 491 | sign = (longwords[0] & 0x80000000) != 0; 492 | 493 | switch (type) { 494 | case SINGLE: 495 | /* 496 | * Format: 497 | * 498 | * 1 bit sign 499 | * 8 bits exponent (biased by 0x7f) 500 | * 23 bits mantissa (implicit leading bit 501 | * left of implied binary point) 502 | */ 503 | exponent = ((longwords[0] >> (32 - (8+1))) & 0xff) - 0x7f; 504 | firstbit = 31 - 22; 505 | lastbit = 31; 506 | zero = zeromantissa(longwords, firstbit, lastbit); 507 | maxexp = 0x80; 508 | minexp = -0x7f; 509 | break; 510 | case DOUBLE: 511 | /* 512 | * Format: 513 | * 514 | * 1 bit sign 515 | * 11 bits exponent (biased by 0x3ff) 516 | * 52 bits mantissa (implicit leading bit 517 | * left of implied binary point) 518 | */ 519 | exponent = ((longwords[0] >> (32 - (11+1))) & 0x7ff) - 0x3ff; 520 | firstbit = 63 - 51; 521 | lastbit = 63; 522 | zero = zeromantissa(longwords, firstbit, lastbit); 523 | maxexp = 0x400; 524 | minexp = -0x3ff; 525 | break; 526 | case EXTENDED: 527 | /* 528 | * Format: 529 | * 530 | * 1 bit sign 531 | * 15 bits exponent (biased by 0x3fff) 532 | * 16 bits unused 533 | * 1 bit explicit leading bit 534 | * left of binary point 535 | * 536 | * 63 bits mantissa (implicit leading bit 537 | * left of implied binary point) 538 | */ 539 | exponent = ((longwords[0] >> (32 - (15+1))) & 0x7fff) - 0x3fff; 540 | firstbit = 95 - 62; 541 | lastbit = 95; 542 | zero = zeromantissa(longwords, firstbit, lastbit); 543 | maxexp = 0x4000; 544 | minexp = -0x3fff; 545 | break; 546 | case PACKED: 547 | /* 548 | * Format: 549 | * 550 | * 1 bit sign 551 | * 1 bit sign of exponent 552 | * 2 bits sign of exponent 553 | * 12 bits 3-digit exponent 554 | * 12 bits unused 555 | * 4 bits explicit leading digit left of decimal point 556 | * 557 | * 64 bits 16-digit (17 with leading digit) mantissa 558 | */ 559 | zero = 1; 560 | firstnonzero = -1; 561 | for (i = 0; i < 17; i++) { 562 | mantissa[i] = longwords[(i + 7) / 8] 563 | >> (((24 - i) % 8) * 4) & 0xf; 564 | if (mantissa[i]) { 565 | zero = 0; 566 | lastnonzero = i; 567 | if (firstnonzero == -1) 568 | firstnonzero = i; 569 | } 570 | } 571 | exponent = (longwords[0] >> 80) & 0xf 572 | + ((longwords[0] >> 84) & 0xf) * 10 573 | + ((longwords[0] >> 88) & 0xf) * 100; 574 | if (longwords[0] & 0x40000000) 575 | exponent = -exponent; 576 | exponent -= firstnonzero; 577 | break; 578 | } 579 | 580 | if (type != PACKED && exponent == maxexp 581 | || type == PACKED && (longwords[0] & 0x7fff0000) == 0x7fff0000) { 582 | if (zero) { 583 | /* Infinity */ 584 | if (sign) 585 | *s++ = '-'; 586 | strcpy(s, "INF"); 587 | } else { 588 | /* NaN */ 589 | strcpy(s, "NaN"); 590 | } 591 | } else if (type != PACKED && exponent == minexp 592 | || type == PACKED && zero) { 593 | if (zero) { 594 | /* Zero */ 595 | strcpy(s, "#0"); 596 | } else { 597 | /* Denormalized */ 598 | strcpy(s, "Denormalized"); 599 | rval = -1; 600 | } 601 | } else if (type != PACKED) { 602 | /* Normalized */ 603 | 604 | double dmantissa; 605 | double exp10; 606 | 607 | dmantissa = stod(longwords, firstbit, lastbit); 608 | if (type == EXTENDED && BIT(longwords, firstbit - 1) == 0) { 609 | /* Unnormalized */ 610 | dmantissa -= 1.0; 611 | while (dmantissa < 1.0) { 612 | dmantissa *= 2.0; 613 | exponent--; 614 | } 615 | } 616 | 617 | *s++ = '#'; 618 | if (sign) 619 | *s++ = '-'; 620 | 621 | /* 622 | * We need to determine if dmantissa * 2^exponent 623 | * is within range or not. 624 | */ 625 | if (exponent < DBL_MAX_EXP && exponent > DBL_MIN_EXP 626 | || exponent == DBL_MAX_EXP 627 | && dmantissa <= DBL_MAX / pow(2.0, DBL_MAX_EXP) 628 | || exponent == DBL_MIN_EXP 629 | && dmantissa <= DBL_MIN / pow(2.0, DBL_MIN_EXP) 630 | ) { 631 | if (exponent) 632 | dmantissa *= pow(2.0, exponent); 633 | sprintf(s, "%g", dmantissa); 634 | } else { 635 | double exp10; 636 | double log10value; 637 | 638 | log10value = log10(dmantissa) 639 | + 0.30102999566398119521 * log10(exponent); 640 | exp10 = floor(log10value); 641 | dmantissa = pow(10.0, log10value - exp10); 642 | s += sprintf(s, "%g", dmantissa); 643 | if (exp10) 644 | sprintf(s, "e%d", dmantissa, (int)exp10); 645 | } 646 | } else /* type == PACKED */ { 647 | *s++ = '#'; 648 | if (sign) 649 | *s++ = '-'; 650 | s += sprintf(s, "%d", mantissa[firstnonzero]); 651 | if (lastnonzero != firstnonzero) 652 | *s++ = '.'; 653 | for (i = firstnonzero + 1; i <= lastnonzero; i++) 654 | s += sprintf(s, "%d", mantissa[i]); 655 | 656 | if (exponent) 657 | sprintf(s, "e%d", exponent); 658 | } 659 | 660 | return rval; 661 | } 662 | 663 | /* 664 | * Read input bytes for floating-point constant 665 | * of floating-point type ``type''. Put formatted value in ``s''. 666 | */ 667 | static int 668 | memfpoint(char *s, int type) 669 | { 670 | u32bit_t longwords[3]; 671 | size_t nlongwords; 672 | int failure; 673 | size_t i; 674 | 675 | switch (type) { 676 | case SINGLE: nlongwords = 1; break; 677 | case DOUBLE: nlongwords = 2; break; 678 | case EXTENDED: case PACKED: 679 | nlongwords = 3; break; 680 | } 681 | 682 | for (i = 0; i < nlongwords; i++) { 683 | longwords[i] = getval(LONGWORD, &failure); 684 | if (failure) 685 | return failure; 686 | } 687 | 688 | return fpoint(longwords, type, s); 689 | } 690 | 691 | /* 692 | * Find effective address given mode/register combination and instruction size. 693 | * Result goes in ``s''. Return 0 for success, else negative. 694 | */ 695 | int 696 | getea(char *s, word_t reg, word_t mode, int size) 697 | { 698 | long longval; 699 | addr_t savedpc; 700 | char creg[3]; 701 | int failure; 702 | 703 | switch (mode) { 704 | case 0: 705 | /* Data register direct */ 706 | sprintf(s, "D%d", reg); 707 | break; 708 | case 1: 709 | /* Address register direct */ 710 | sprintf(s, "%2.2s", Areg(reg)); 711 | break; 712 | case 2: 713 | /* Address register indirect */ 714 | sprintf(s, "(%2.2s)", Areg(reg)); 715 | break; 716 | case 3: 717 | /* Address register indirect with postincrement */ 718 | sprintf(s, "(%2.2s)+", Areg(reg)); 719 | break; 720 | case 4: 721 | /* Address register indirect with predecrement */ 722 | sprintf(s, "-(%2.2s)", Areg(reg)); 723 | break; 724 | case 5: 725 | /* Address register indirect with displacement */ 726 | longval = getval(WORD, &failure); 727 | if (failure) 728 | return failure; 729 | if (CPU(chip) >= MC68020) 730 | sprintf(s, "(%ld,%2.2s)", longval, Areg(reg)); 731 | else 732 | sprintf(s, "%ld(%2.2s)", longval, Areg(reg)); 733 | break; 734 | case 6: 735 | /* 736 | * Address register indirect 737 | * with index and displacement 738 | */ 739 | sprintf(creg, "%2.2s", Areg(reg)); 740 | return extended(s, creg, size); 741 | break; 742 | case 7: 743 | switch (reg) { 744 | case 0: 745 | /* Absolute short */ 746 | longval = getval(WORD, &failure); 747 | if (failure) 748 | return failure; 749 | sprintf(s, "$%0*lx.W", 2 * sizeof(word_t), longval); 750 | break; 751 | case 1: 752 | /* Absolute long */ 753 | longval = getval(LONGWORD, &failure); 754 | if (failure) 755 | return failure; 756 | sprintf(s, "$%0*lx.L", 4 * sizeof(word_t), longval); 757 | break; 758 | case 2: 759 | /* Program counter indirect with displacement */ 760 | savedpc = pc; 761 | longval = getval(WORD, &failure); 762 | if (failure) 763 | return failure; 764 | 765 | if (pass == DCLABELSPASS) { 766 | if (longval + savedpc >= initialpc 767 | && longval + savedpc <= initialpc 768 | + maxoffset) { 769 | insts[longval + savedpc 770 | - initialpc].flags |= ISLABEL; 771 | if (!insts[longval + savedpc 772 | - initialpc].size && 773 | insts[ppc - initialpc].flags & ISFPU) 774 | insts[longval + savedpc 775 | - initialpc].flags 776 | |= ftype2lis(size); 777 | } 778 | } else if (pass == FIRSTPASS && pcrelative) { 779 | required[flags & 3] = longval + savedpc; 780 | flags++; 781 | } else if (pass == LASTPASS 782 | && longval + savedpc >= initialpc 783 | && longval + savedpc <= initialpc + maxoffset 784 | && insts[longval + savedpc - initialpc].labelnum) 785 | sprintf(s, "L%d", 786 | insts[longval + savedpc - initialpc].labelnum); 787 | else /* if ((pass == FIRSTPASS || pass == LASTPASS) 788 | && !pcrelative 789 | || pass == DEBUGPASS 790 | || pass == LASTPASS && pcrelative 791 | && longval + savedpc > initialpc + maxoffset) */ { 792 | if (longval == 0) 793 | sprintf(s, "(PC)!$%lx", savedpc); 794 | else if (CPU(chip) >= MC68020) 795 | sprintf(s, "(%ld,PC)!$%lx", longval, 796 | longval + savedpc); 797 | else 798 | sprintf(s, "%ld(PC)!$%lx", longval, 799 | longval + savedpc); 800 | } 801 | break; 802 | case 3: 803 | /* 804 | * Program counter indirect 805 | * with index and displacement 806 | */ 807 | return extended(s, "PC", size); 808 | break; 809 | case 4: 810 | /* Immediate */ 811 | switch (size) { 812 | case BYTE: /* FALLTHROUGH */ 813 | case WORD: /* FALLTHROUGH */ 814 | case LONGWORD: /* FALLTHROUGH */ 815 | case DOUBLELONGWORD: 816 | s[0] = '#'; 817 | longval = getval(size == DOUBLELONGWORD 818 | ? LONGWORD : size, &failure); 819 | if (failure) 820 | return failure; 821 | s += immsprintf(s + 1, longval) + 1; 822 | if (size == DOUBLELONGWORD) { 823 | s[0] = '/'; 824 | longval = getval(LONGWORD, &failure); 825 | if (failure) 826 | return failure; 827 | immsprintf(s + 1, longval); 828 | } 829 | break; 830 | case SINGLE: /* FALLTHROUGH */ 831 | case DOUBLE: /* FALLTHROUGH */ 832 | case EXTENDED: /* FALLTHROUGH */ 833 | case PACKED: 834 | #if 0 835 | if (memfpoint(s, size) == -1) 836 | return -1; 837 | #endif 838 | (void)memfpoint(s, size); 839 | } 840 | break; 841 | default: 842 | return -1; 843 | } 844 | } 845 | 846 | return 0; 847 | } 848 | 849 | /* 850 | * If printing is appropriate, print an output line. 851 | * The instruction name is given in ``name'' and ``lflags'' tells about 852 | * the instruction operands (the ellipsis arguments). 853 | */ 854 | void 855 | instprint(int lflags, const char *name, ...) 856 | { 857 | va_list ap; 858 | int operands = f2ops(lflags); 859 | char *cp; 860 | size_t i; 861 | int tabs, spaces; 862 | 863 | va_start(ap, name); 864 | 865 | if (pass == LASTPASS || pass == DEBUGPASS) { 866 | fprintf(outfp, "%08x", (int)ppc); 867 | if (lower) 868 | for (i = 0; i < leninstbuf; i++) 869 | instbuf[i] = tolower(instbuf[i]); 870 | fprintf(outfp, " %.*s", (int)leninstbuf, instbuf); 871 | #define TABSIZE 8 872 | if ((tabs = (36 - leninstbuf) / TABSIZE) <= 0) 873 | tabs = 1; 874 | while (tabs--) 875 | (void)putc('\t', outfp); 876 | #undef TABSIZE 877 | 878 | if (pass == LASTPASS && insts[ppc - initialpc].labelnum) 879 | fprintf(outfp, "L%d", insts[ppc - initialpc].labelnum); 880 | (void)putc('\t', outfp); 881 | if (lower) { 882 | char *newname; 883 | size_t len = strlen(name); 884 | 885 | if (newname = malloc(len + 1)) { 886 | for (i = 0; i < len; i++) 887 | newname[i] = tolower(name[i]); 888 | newname[len] = '\0'; 889 | fprintf(outfp, "%s", newname); 890 | free(newname); 891 | } else 892 | fprintf(outfp, "%s", name); 893 | } else 894 | fprintf(outfp, "%s", name); 895 | if (lower) { 896 | if (lflags & PBYTE) 897 | fprintf(outfp, ".b"); 898 | else if (lflags & PWORD) 899 | fprintf(outfp, ".w"); 900 | else if (lflags & PLONGWORD) 901 | fprintf(outfp, ".l"); 902 | else if (lflags & PDOUBLELONGWORD) 903 | fprintf(outfp, ".dl"); 904 | else if (lflags & PSINGLE) 905 | fprintf(outfp, ".s"); 906 | else if (lflags & PDOUBLE) 907 | fprintf(outfp, ".d"); 908 | else if (lflags & PEXTENDED) 909 | fprintf(outfp, ".x"); 910 | else if (lflags & PPACKED) 911 | fprintf(outfp, ".p"); 912 | } else { 913 | if (lflags & PBYTE) 914 | fprintf(outfp, ".B"); 915 | else if (lflags & PWORD) 916 | fprintf(outfp, ".W"); 917 | else if (lflags & PLONGWORD) 918 | fprintf(outfp, ".L"); 919 | else if (lflags & PDOUBLELONGWORD) 920 | fprintf(outfp, ".DL"); 921 | else if (lflags & PSINGLE) 922 | fprintf(outfp, ".S"); 923 | else if (lflags & PDOUBLE) 924 | fprintf(outfp, ".D"); 925 | else if (lflags & PEXTENDED) 926 | fprintf(outfp, ".X"); 927 | else if (lflags & PPACKED) 928 | fprintf(outfp, ".P"); 929 | } 930 | 931 | for (i = 1; i <= operands; i++) { 932 | putc(i == 1 ? '\t' : ',', outfp); 933 | if (lflags & sharp2f(i)) 934 | putc('#', outfp); 935 | cp = va_arg(ap, char *); 936 | if (lower && (cp[0] != 'L' || !isdigit(cp[1]))) { 937 | char *cp2 = cp - 1; 938 | 939 | while (*++cp2) 940 | *cp2 = tolower(*cp2); 941 | } 942 | fprintf(outfp, "%s", cp); 943 | } 944 | putc('\n', outfp); 945 | } 946 | 947 | leninstbuf = 0; 948 | ppc = pc; 949 | 950 | va_end(ap); 951 | } 952 | 953 | /* 954 | * Format a range of registers (``low'' to ``high'') 955 | * into ``s'', beginning with a ``slash'' if necessary. 956 | * ``ad'' specifies either address (A) or data (D) registers. 957 | */ 958 | static char * 959 | regwrite(char *s, char *ad, int low, int high, int slash) 960 | { 961 | if (slash) 962 | *s++ = '/'; 963 | if (high - low > 1) { 964 | s += sprintf(s, "%s", ad); 965 | *s++ = low + '0'; 966 | *s++ = '-'; 967 | s += sprintf(s, "%s", ad); 968 | *s++ = high + '0'; 969 | } else if (high - low == 1) { 970 | s += sprintf(s, "%s", ad); 971 | *s++ = low + '0'; 972 | *s++ = '/'; 973 | s += sprintf(s, "%s", ad); 974 | *s++ = high + '0'; 975 | } else { 976 | s += sprintf(s, "%s", ad); 977 | *s++ = high + '0'; 978 | } 979 | *s = '\0'; 980 | 981 | return s; 982 | } 983 | 984 | /* 985 | * Format ``regmask'' into ``s''. ``ad'' is a prefix used to indicate 986 | * whether the mask is for address, data, or floating-point registers. 987 | */ 988 | char * 989 | regbyte(char *s, unsigned char regmask, char *ad, int doslash) 990 | { 991 | int i; 992 | int last; 993 | 994 | for (last = -1, i = 0; regmask; i++, regmask >>= 1) 995 | if (regmask & 1) { 996 | if (last != -1) 997 | continue; 998 | else 999 | last = i; 1000 | } else if (last != -1) { 1001 | s = regwrite(s, ad, last, i - 1, doslash); 1002 | doslash = 1; 1003 | last = -1; 1004 | } 1005 | 1006 | if (last != -1) 1007 | s = regwrite(s, ad, last, i - 1, doslash); 1008 | 1009 | return s; 1010 | } 1011 | 1012 | /* 1013 | * Reverse the ``nbits'' bits in ``bits''. 1014 | * Used to change register masks. 1015 | */ 1016 | void 1017 | revbits(unsigned long *bits, size_t nbits) 1018 | { 1019 | int i; 1020 | int b1, b2; 1021 | 1022 | for (i = 0; i < nbits / 2; i++) { 1023 | b1 = *bits & (1 << i); 1024 | b2 = *bits & (1 << (nbits - 1 - i)); 1025 | if (b1) 1026 | *bits |= 1 << (nbits - 1 - i); 1027 | else 1028 | *bits &= ~(1 << (nbits - 1 - i)); 1029 | if (b2) 1030 | *bits |= 1 << i; 1031 | else 1032 | *bits &= ~(1 << i); 1033 | } 1034 | } 1035 | -------------------------------------------------------------------------------- /inst2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christopher G. Phillips 3 | * Copyright (C) 1994 All Rights Reserved 4 | * 5 | * NOTICE 6 | * 7 | * Permission to use, copy, modify, and distribute this software and 8 | * its documentation for any purpose and without fee is hereby granted 9 | * provided that the above copyright notice appear in all copies and 10 | * that both the copyright notice and this permission notice appear in 11 | * supporting documentation. 12 | * 13 | * The author makes no representations about the suitability of this 14 | * software for any purpose. This software is provided ``as is'' 15 | * without express or implied warranty. 16 | */ 17 | 18 | /* 19 | * Most of the functions that determine whether an instruction is valid 20 | * and then print it (as necessary) are here. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "dis.h" 27 | #include "addr.h" 28 | 29 | void 30 | bit_dynamic(word_t inst) 31 | { 32 | int destreg = inst & 7; 33 | int destmode = (inst >> 3) & 7; 34 | int type = (inst >> 6) & 3; 35 | int srcreg = (inst >> 9) & 7; 36 | int size = (destmode == 0) ? LONGWORD : BYTE; 37 | char name[10]; 38 | 39 | if (type == 0) { 40 | /* BTST */ 41 | if (!ISDEA(destmode, destreg)) 42 | return; 43 | } else { 44 | /* BCHG, BCLR, BSET */ 45 | if (!ISADEA(destmode, destreg)) 46 | return; 47 | } 48 | 49 | sprintf(name, "B%s", bitd[type]); 50 | if (getea(buf2, destreg, destmode, size)) 51 | return; 52 | sprintf(buf1, "D%d", srcreg); 53 | instprint(ops2f(2) | size2f(size), name, buf1, buf2); 54 | 55 | valid = 1; 56 | } 57 | 58 | void 59 | bit_static(word_t inst) 60 | { 61 | int reg = inst & 7; 62 | int mode = (inst >> 3) & 7; 63 | int type = (inst >> 6) & 3; 64 | int size = (ISDATA(mode)) ? LONGWORD : BYTE; 65 | long value; 66 | int failure; 67 | char name[10]; 68 | 69 | if (type == 0) { 70 | /* BTST */ 71 | if (!ISDEAlessIMM(mode, reg)) 72 | return; 73 | } else { 74 | /* BCHG, BCLR, BSET */ 75 | if (!ISADEA(mode, reg)) 76 | return; 77 | } 78 | 79 | value = getval(/* BYTE */ WORD, &failure); 80 | if (failure) 81 | return; 82 | if (value & 0xff00) 83 | return; 84 | if (!ISDATA(mode)) 85 | value %= 8; 86 | 87 | sprintf(name, "B%s", bitd[type]); 88 | if (getea(buf2, reg, mode, size)) 89 | return; 90 | immsprintf(buf1, value); 91 | instprint(ops2f(2) | size2f(size) | sharp2f(1), name, buf1, buf2); 92 | 93 | valid = 1; 94 | } 95 | 96 | void 97 | biti_reg(const char *name, int size, const char *reg) 98 | { 99 | long value; 100 | int failure; 101 | 102 | value = getval(size, &failure); 103 | if (failure) 104 | return; 105 | immsprintf(buf1, value); 106 | instprint(ops2f(2) | size2f(size) | sharp2f(1), name, buf1, reg); 107 | 108 | if (size == BYTE && (value & 0xff00)) 109 | return; 110 | 111 | valid = 1; 112 | } 113 | 114 | void 115 | biti_size(const char *name, word_t inst) 116 | { 117 | int reg = inst & 7; 118 | int mode = (inst >> 3) & 7; 119 | int size = (inst >> 6) & 3; 120 | long value; 121 | int failure; 122 | 123 | if (name[0] == 'C') { 124 | /* CMPI */ 125 | if (!ISDEAlessIMM(mode, reg)) 126 | return; 127 | } else { 128 | /* ADDI, ANDI, EORI, ORI, SUBI */ 129 | if (!ISADEA(mode, reg)) 130 | return; 131 | } 132 | 133 | value = getval(size, &failure); 134 | if (failure) 135 | return; 136 | 137 | immsprintf(buf1, value); 138 | if (getea(buf2, reg, mode, size)) 139 | return; 140 | instprint(ops2f(2) | size2f(size) | sharp2f(1), name, buf1, buf2); 141 | 142 | valid = 1; 143 | } 144 | 145 | void 146 | cmp2_chk2(word_t inst) 147 | { 148 | int srcreg = inst & 7; 149 | int srcmode = (inst >> 3) & 7; 150 | int size = (inst >> 9) & 3; 151 | long value; 152 | int failure; 153 | int destreg; 154 | 155 | if (!ISCEA(srcmode, srcreg)) 156 | return; 157 | 158 | value = getval(WORD, &failure); 159 | if (failure) 160 | return; 161 | if (getea(buf1, srcreg, srcmode, size)) 162 | return; 163 | destreg = (value >> 12) & 7; 164 | Areg2(buf2, (value & 0x8000) ? 'A' : 'D', destreg); 165 | instprint(ops2f(2) | size2f(size), (value & 0x0800) ? "CHK2" : "CMP2", 166 | buf1, buf2); 167 | 168 | if (value & 0x07ff) 169 | return; 170 | 171 | valid = 1; 172 | } 173 | 174 | void 175 | movep(word_t inst) 176 | { 177 | int addrreg = inst & 7; 178 | int datareg = (inst >> 9) & 7; 179 | int opmode = (inst >> 6) & 7; 180 | int size = (opmode & 1) ? LONGWORD : WORD; 181 | long value; 182 | int failure; 183 | 184 | value = getval(WORD, &failure); 185 | if (failure) 186 | return; 187 | 188 | sprintf(buf1, "D%d", datareg); 189 | immsprintf(buf2, value); 190 | sprintf(buf2 + strlen(buf2), "(%2.2s)", Areg(addrreg)); 191 | if (opmode & 2) 192 | instprint(ops2f(2) | size2f(size) | sharp2f(2), "MOVEP", 193 | buf1, buf2); 194 | else 195 | instprint(ops2f(2) | size2f(size) | sharp2f(1), "MOVEP", 196 | buf2, buf1); 197 | 198 | valid = 1; 199 | } 200 | 201 | void 202 | cas(word_t inst) 203 | { 204 | int reg = inst & 7; 205 | int mode = (inst >> 3) & 7; 206 | int size; 207 | int comparereg; 208 | int updatereg; 209 | long value; 210 | int failure; 211 | 212 | if (!ISAMEA(mode, reg)) 213 | return; 214 | 215 | switch ((inst >> 9) & 3) { 216 | case 1: size = BYTE; break; 217 | case 2: size = WORD; break; 218 | case 3: size = LONGWORD; break; 219 | } 220 | 221 | value = getval(WORD, &failure); 222 | comparereg = value & 7; 223 | updatereg = (value >> 6) & 7; 224 | if (failure) 225 | return; 226 | 227 | sprintf(buf1, "D%d", comparereg); 228 | sprintf(buf2, "D%d", updatereg); 229 | if (getea(buf3, reg, mode, size)) 230 | return; 231 | instprint(ops2f(3) | size2f(size), "CAS", buf1, buf2, buf3); 232 | 233 | if (value & 0xfe38) 234 | return; 235 | 236 | valid = 1; 237 | } 238 | 239 | void 240 | cas2(word_t inst) 241 | { 242 | int size = (inst & 0x0200) ? LONGWORD : WORD; 243 | long value[2]; 244 | int failure; 245 | int comparereg[2]; 246 | int updatereg[2]; 247 | int reg[2]; 248 | int anotd[2]; 249 | int i; 250 | 251 | for (i = 0; i < 2; i++) { 252 | value[i] = getval(WORD, &failure); 253 | if (failure) 254 | return; 255 | comparereg[i] = value[i] & 7; 256 | updatereg[i] = (value[i] >> 6) & 7; 257 | reg[i] = (value[i] >> 12) & 7; 258 | anotd[i] = (value[i] & 0x8000) ? 'A' : 'D'; 259 | } 260 | 261 | sprintf(buf1, "D%d:D%d", comparereg[0], comparereg[1]); 262 | sprintf(buf2, "D%d:D%d", updatereg[0], updatereg[1]); 263 | Areg2(buf3, anotd[0], reg[0]); 264 | buf3[2] = ':'; 265 | Areg2(&buf3[3], anotd[1], reg[1]); 266 | instprint(ops2f(3) | size2f(size), "CAS2", buf1, buf2, buf3); 267 | 268 | valid = 1; 269 | } 270 | 271 | void 272 | moves(word_t inst) 273 | { 274 | int srcreg = inst & 7; 275 | int srcmode = (inst >> 3) & 7; 276 | int size = (inst >> 6) & 3; 277 | long value; 278 | int failure; 279 | int reg; 280 | int anotd; 281 | char *cp1 = buf1, *cp2 = buf2; 282 | 283 | if (!ISAMEA(srcmode, srcreg)) 284 | return; 285 | value = getval(WORD, &failure); 286 | if (failure) 287 | return; 288 | 289 | reg = (value >> 12) & 7; 290 | anotd = (value & 0x8000) ? 'A' : 'D'; 291 | if (getea(buf1, srcreg, srcmode, size)) 292 | return; 293 | Areg2(buf2, anotd, reg); 294 | if (value & 0x0800) { 295 | cp1 = buf2; 296 | cp2 = buf1; 297 | } 298 | 299 | instprint(ops2f(2) | size2f(size), "MOVES", cp1, cp2); 300 | 301 | if (value & 0x07ff) 302 | return; 303 | 304 | valid = 1; 305 | } 306 | 307 | void 308 | move(word_t inst, int size) 309 | { 310 | int srcreg, destreg; 311 | int srcmode, destmode; 312 | 313 | srcreg = inst & 7; 314 | srcmode = (inst >> 3) & 7; 315 | destmode = (inst >> 6) & 7; 316 | destreg = (inst >> 9) & 7; 317 | 318 | if (ISDIRECT(destmode)) { 319 | if (size == BYTE) 320 | return; 321 | } else if (size == BYTE && ISDIRECT(srcmode) 322 | || !ISAEA(destmode, destreg)) 323 | return; 324 | 325 | if (getea(buf1, srcreg, srcmode, size)) 326 | return; 327 | if (ISDIRECT(destmode)) { 328 | sprintf(buf2, "%2.2s", Areg(destreg)); 329 | instprint(ops2f(2) | size2f(size), "MOVEA", buf1, buf2); 330 | } else { 331 | if (getea(buf2, destreg, destmode, size)) 332 | return; 333 | instprint(ops2f(2) | size2f(size), "MOVE", buf1, buf2); 334 | } 335 | 336 | valid = 1; 337 | } 338 | 339 | void 340 | misc_size(const char *name, word_t inst) 341 | { 342 | int reg = inst & 7; 343 | int mode = (inst >> 3) & 7; 344 | int size = (inst >> 6) & 3; 345 | 346 | if (name[0] == 'T') { 347 | /* TST */ 348 | if (size == BYTE && !ISDEAlessIMM(mode, reg)) 349 | return; 350 | } else { 351 | /* CLR, NEG, NEGX, NOT */ 352 | if (!ISADEA(mode, reg)) 353 | return; 354 | } 355 | 356 | if (getea(buf1, reg, mode, size)) 357 | return; 358 | instprint(ops2f(1) | size2f(size), name, buf1); 359 | 360 | valid = 1; 361 | } 362 | 363 | void 364 | misc_ea(const char *name, word_t inst, int size) 365 | { 366 | int reg = inst & 7; 367 | int mode = (inst >> 3) & 7; 368 | 369 | if (name[1] < 'C') { 370 | /* NBCD, TAS */ 371 | if (!ISADEA(mode, reg)) 372 | return; 373 | } else { 374 | /* JMP, JSR, PEA */ 375 | if (!ISCEA(mode, reg)) 376 | return; 377 | } 378 | if (getea(buf1, reg, mode, size)) 379 | return; 380 | instprint(ops2f(1), name, buf1); 381 | 382 | valid = 1; 383 | } 384 | 385 | void 386 | chk(word_t inst) 387 | { 388 | int srcreg = inst & 7; 389 | int srcmode = (inst >> 3) & 7; 390 | int destreg = (inst >> 9) & 7; 391 | 392 | if (!ISDEA(srcmode, srcreg)) 393 | return; 394 | 395 | if (getea(buf1, srcreg, srcmode, WORD)) 396 | return; 397 | sprintf(buf2, "D%d", destreg); 398 | instprint(ops2f(2), "CHK", buf1, buf2); 399 | 400 | valid = 1; 401 | } 402 | 403 | void 404 | lea(word_t inst) 405 | { 406 | int srcreg = inst & 7; 407 | int srcmode = (inst >> 3) & 7; 408 | int destreg = (inst >> 9) & 7; 409 | int retval; 410 | 411 | if (!ISCEA(srcmode, srcreg)) 412 | return; 413 | retval = getea(buf1, srcreg, srcmode, LONGWORD); 414 | if (retval) 415 | return; 416 | sprintf(buf2, "%2.2s", Areg(destreg)); 417 | instprint(ops2f(2), "LEA", buf1, buf2); 418 | 419 | valid = 1; 420 | } 421 | 422 | void 423 | link(word_t inst, int size) 424 | { 425 | int reg = inst & 7; 426 | long value; 427 | int failure; 428 | 429 | value = getval(size, &failure); 430 | if (failure) 431 | return; 432 | sprintf(buf1, "%2.2s", Areg(reg)); 433 | sprintf(buf2, "%ld", value); 434 | instprint(ops2f(2) | sharp2f(2), "LINK", buf1, buf2); 435 | 436 | valid = 1; 437 | } 438 | 439 | void 440 | unlk(word_t inst) 441 | { 442 | int reg = inst & 7; 443 | 444 | sprintf(buf1, "%2.2s", Areg(reg)); 445 | instprint(ops2f(1), "UNLK", buf1); 446 | 447 | valid = 1; 448 | } 449 | 450 | void 451 | swap(word_t inst) 452 | { 453 | int reg = inst & 7; 454 | 455 | sprintf(buf1, "D%d", reg); 456 | instprint(ops2f(1), "SWAP", buf1); 457 | 458 | valid = 1; 459 | } 460 | 461 | void 462 | bkpt(word_t inst) 463 | { 464 | int vector = inst & 0xf; 465 | 466 | sprintf(buf1, "%d", vector); 467 | instprint(ops2f(1) | sharp2f(1), "BKPT", buf1); 468 | 469 | valid = 1; 470 | } 471 | 472 | void 473 | trap(word_t inst) 474 | { 475 | int vector = inst & 0xf; 476 | 477 | sprintf(buf1, "%d", vector); 478 | instprint(ops2f(1) | sharp2f(1), "TRAP", buf1); 479 | 480 | valid = 1; 481 | } 482 | 483 | void 484 | stop_rtd(const char *name) 485 | { 486 | int value; 487 | int failure; 488 | 489 | value = getval(WORD, &failure); 490 | if (failure) 491 | return; 492 | 493 | sprintf(buf1, "%ld", value); 494 | instprint(ops2f(1) | sharp2f(1), name, buf1); 495 | 496 | valid = 1; 497 | } 498 | 499 | void 500 | movec(int tocr) 501 | { 502 | long value; 503 | int failure; 504 | int reg; 505 | int anotd; 506 | int controlreg; 507 | char *cr; 508 | char *cp1; 509 | char *cp2; 510 | 511 | value = getval(WORD, &failure); 512 | if (failure) 513 | return; 514 | 515 | reg = (value >> 12) & 7; 516 | anotd = (value & 0x8000) ? 'A' : 'D'; 517 | controlreg = value & 0x0fff; 518 | 519 | Areg2(buf1, anotd, reg); 520 | switch (controlreg) { 521 | case 0x000: cr = "SFC"; break; /* Source Function Code */ 522 | case 0x001: cr = "DFC"; break; /* Destination Function Code */ 523 | case 0x002: cr = "CACR"; break; /* Cache Control Register */ 524 | case 0x800: cr = "USP"; break; /* User Stack Pointer */ 525 | case 0x801: cr = "VBR"; break; /* Vector Base Register */ 526 | case 0x802: cr = "CAAR"; break; /* Cache Address Register */ 527 | case 0x803: cr = "MSP"; break; /* Master Stack Pointer */ 528 | case 0x804: cr = "ISP"; break; /* Interrupt Stack Pointer */ 529 | default: 530 | return; 531 | } 532 | 533 | if (tocr) { 534 | cp1 = buf1; 535 | cp2 = cr; 536 | } else { 537 | cp1 = cr; 538 | cp2 = buf1; 539 | } 540 | 541 | instprint(ops2f(2), "MOVEC", cp1, cp2); 542 | 543 | valid = 1; 544 | } 545 | 546 | void 547 | ext(word_t inst) 548 | { 549 | int reg = inst & 3; 550 | int opmode = (inst >> 6) & 3; 551 | int size = (opmode == 2) ? WORD : LONGWORD; 552 | char sext[5]; 553 | 554 | sprintf(buf1, "D%d", reg); 555 | strcpy(sext, "EXT"); 556 | if (inst & 0x0100) 557 | strcat(sext, "B"); 558 | instprint(ops2f(1) | size2f(size), sext, buf1); 559 | 560 | valid = 1; 561 | } 562 | 563 | void 564 | movereg(word_t inst, const char *regname, int to) 565 | { 566 | int reg = inst & 7; 567 | int mode = (inst >> 3) & 7; 568 | const char *cp1, *cp2; 569 | 570 | if (getea(buf1, reg, mode, WORD)) 571 | return; 572 | if (to) { 573 | if (!ISDEA(mode, reg)) 574 | return; 575 | cp1 = buf1; 576 | cp2 = regname; 577 | } else { 578 | if (!ISADEA(mode, reg)) 579 | return; 580 | cp1 = regname; 581 | cp2 = buf1; 582 | } 583 | 584 | instprint(ops2f(2) | size2f(WORD), "MOVE", cp1, cp2); 585 | 586 | valid = 1; 587 | } 588 | 589 | void 590 | moveusp(word_t inst, int to) 591 | { 592 | int reg = inst & 7; 593 | char *cp1 = buf1, *cp2 = "USP"; 594 | 595 | sprintf(buf1, "%2.2s", Areg(reg)); 596 | if (!to) { 597 | cp1 = cp2; 598 | cp2 = buf1; 599 | } 600 | 601 | instprint(ops2f(2) | size2f(LONGWORD), "MOVE", cp1, cp2); 602 | 603 | valid = 1; 604 | } 605 | 606 | static void 607 | reglist(char *s, unsigned long regmask, int mode) 608 | { 609 | char *t = s; 610 | 611 | if (mode == 4) 612 | revbits(®mask, 16); 613 | s = regbyte(s, regmask & 0xff, "D", 0); 614 | s = regbyte(s, regmask >> 8, "A", s != t); 615 | if (s == t) 616 | strcpy(s, "0"); 617 | } 618 | 619 | void 620 | movem(word_t inst, int to) 621 | { 622 | int reg = inst & 7; 623 | int mode = (inst >> 3) & 7; 624 | int size = (inst & 0x40) ? LONGWORD : WORD; 625 | unsigned long regmask; 626 | int failure; 627 | char *cp1, *cp2; 628 | 629 | regmask = getval(WORD, &failure) & 0xffff; 630 | if (failure) 631 | return; 632 | if (getea(buf1, reg, mode, size)) 633 | return; 634 | reglist(buf2, regmask, mode); 635 | if (to) { 636 | if (!ISCEAplusPOST(mode, reg)) 637 | return; 638 | cp1 = buf1; 639 | cp2 = buf2; 640 | } else { 641 | if (!ISACEAplusPRE(mode, reg)) 642 | return; 643 | cp1 = buf2; 644 | cp2 = buf1; 645 | } 646 | 647 | instprint(ops2f(2) | size2f(size), "MOVEM", cp1, cp2); 648 | 649 | valid = 1; 650 | } 651 | 652 | void 653 | dbcc(word_t inst) 654 | { 655 | int reg = inst & 7; 656 | int condition = (inst >> 8) & 0xf; 657 | long value; 658 | int failure; 659 | char sdbcc[5]; 660 | addr_t savedpc; 661 | short f = ops2f(2); 662 | 663 | sprintf(sdbcc, "DB%s", condition == 1 ? "RA" : cc[condition]); 664 | sprintf(buf1, "D%d", reg); 665 | savedpc = pc; 666 | value = getval(WORD, &failure); 667 | if (failure) 668 | return; 669 | 670 | if (pass == FIRSTPASS && onepass != INCONSISTENT) { 671 | required[flags & 3] = value + savedpc; 672 | flags++; 673 | } else if (pass == LASTPASS && value + savedpc >= initialpc 674 | && value + savedpc <= initialpc + maxoffset 675 | && insts[value + savedpc - initialpc].labelnum) 676 | sprintf(buf2, "L%d", 677 | insts[value + savedpc - initialpc].labelnum); 678 | else /* if (pass == DEBUGPASS 679 | || value + savedpc > initialpc + maxoffset) */ 680 | /* immsprintf(buf2, value); */ 681 | sprintf(buf2, "%lx", (long)(value + savedpc)); 682 | instprint(f, sdbcc, buf1, buf2); 683 | 684 | valid = 1; 685 | } 686 | 687 | void 688 | trapcc(word_t inst) 689 | { 690 | int mode = inst & 7; 691 | int condition = (inst >> 8) & 0xf; 692 | long value = 0; 693 | int failure; 694 | int lflags; 695 | 696 | sprintf(buf1, "TRAP%s", cc[condition]); 697 | switch (mode) { 698 | case 2: 699 | value = getval(WORD, &failure); 700 | if (failure) 701 | return; 702 | lflags = ops2f(1) | size2f(WORD) | sharp2f(1); 703 | break; 704 | case 3: 705 | value = getval(LONGWORD, &failure); 706 | if (failure) 707 | return; 708 | lflags = ops2f(1) | size2f(LONGWORD) | sharp2f(1); 709 | break; 710 | case 4: 711 | lflags = ops2f(0); 712 | break; 713 | default: 714 | return; 715 | } 716 | 717 | sprintf(buf2, "%ld", value); 718 | 719 | instprint(lflags, buf1, buf2); 720 | 721 | valid = 1; 722 | } 723 | 724 | void 725 | scc(word_t inst) 726 | { 727 | int reg = inst & 7; 728 | int mode = (inst >> 3) & 7; 729 | int condition = (inst >> 8) & 0xf; 730 | 731 | if (!ISADEA(mode, reg)) 732 | return; 733 | sprintf(buf1, "S%s", cc[condition]); 734 | if (getea(buf2, reg, mode, BYTE)) 735 | return; 736 | instprint(ops2f(1) | sharp2f(2), buf1, buf2); 737 | 738 | valid = 1; 739 | } 740 | 741 | void 742 | pack_unpk(const char *name, word_t inst) 743 | { 744 | int reg1 = inst & 7; 745 | int reg2 = (inst >> 9) & 7; 746 | long value; 747 | int failure; 748 | 749 | if (inst & 8) { 750 | sprintf(buf1, "-(%2.2s)", Areg(reg1)); 751 | sprintf(buf2, "-(%2.2s)", Areg(reg2)); 752 | } else { 753 | sprintf(buf1, "D%d", reg1); 754 | sprintf(buf2, "D%d", reg2); 755 | } 756 | 757 | value = getval(WORD, &failure); 758 | if (failure) 759 | return; 760 | immsprintf(buf3, value); 761 | instprint(ops2f(3) | sharp2f(3), name, buf1, buf2, buf3); 762 | 763 | valid = 1; 764 | } 765 | 766 | void 767 | addq_subq(word_t inst) 768 | { 769 | int reg = inst & 7; 770 | int mode = (inst >> 3) & 7; 771 | int size = (inst >> 6) & 3; 772 | int data; 773 | 774 | if (!ISAEA(mode, reg) || ISDIRECT(mode) && size == BYTE) 775 | return; 776 | 777 | if ((data = (inst >> 9) & 7) == 0) 778 | data = 8; 779 | sprintf(buf1, "%d", data); 780 | if (getea(buf2, reg, mode, size)) 781 | return; 782 | instprint(ops2f(2) | size2f(size) | sharp2f(1), 783 | (inst & 0x0100) ? "SUBQ" : "ADDQ", buf1, buf2); 784 | 785 | valid = 1; 786 | } 787 | 788 | void 789 | op1(const char *name, word_t inst) 790 | { 791 | int datareg = (inst >> 9) & 7; 792 | int reg = inst & 7; 793 | int mode = (inst >> 3) & 7; 794 | int size = (inst >> 6) & 3; 795 | char *cp1, *cp2; 796 | 797 | if (getea(buf1, reg, mode, size)) 798 | return; 799 | sprintf(buf2, "D%d", datareg); 800 | if (inst & 0x0100) { 801 | if (name[0] == 'E') { 802 | /* EOR */ 803 | if (!ISADEA(mode, reg)) 804 | return; 805 | } else { 806 | /* ADD, AND, OR, SUB */ 807 | if (!ISAMEA(mode, reg)) 808 | return; 809 | } 810 | cp1 = buf2; 811 | cp2 = buf1; 812 | } else { 813 | if (name[0] == 'O' || name[1] == 'N') { 814 | /* AND, OR */ 815 | if (!ISDEA(mode, reg)) 816 | return; 817 | } else { 818 | /* ADD, CMP, SUB */ 819 | if (ISDIRECT(mode) && size == BYTE) 820 | return; 821 | } 822 | cp1 = buf1; 823 | cp2 = buf2; 824 | } 825 | instprint(ops2f(2) | size2f(size), name, cp1, cp2); 826 | 827 | valid = 1; 828 | } 829 | 830 | void 831 | op2(const char *name, word_t inst) 832 | { 833 | int datareg = (inst >> 9) & 7; 834 | int reg = inst & 7; 835 | int mode = (inst >> 3) & 7; 836 | char realname[10]; 837 | 838 | if (!ISDEA(mode, reg)) 839 | return; 840 | strcpy(realname, name); 841 | strcat(realname, ((inst >> 8) & 1) ? "S" : "U"); 842 | if (getea(buf1, reg, mode, WORD)) 843 | return; 844 | sprintf(buf2, "D%d", datareg); 845 | instprint(ops2f(2) | size2f(WORD), realname, buf1, buf2); 846 | 847 | valid = 1; 848 | } 849 | 850 | void 851 | op2long(const char *name, word_t inst) 852 | { 853 | int reg = inst & 7; 854 | int mode = (inst >> 3) & 7; 855 | char realname[10]; 856 | long value; 857 | int failure; 858 | int rreg; 859 | int qreg; 860 | int quadword_dividend; 861 | 862 | if (!ISDEA(mode, reg)) 863 | return; 864 | value = getval(WORD, &failure); 865 | if (failure) 866 | return; 867 | if (value & 0x83f8) 868 | return; 869 | 870 | rreg = value & 7; 871 | qreg = (value >> 12) & 7; 872 | quadword_dividend = value & 0x0400; 873 | 874 | strcpy(realname, name); 875 | strcat(realname, (value & 0x0800) ? "S" : "U"); 876 | if (realname[0] == 'D' && rreg != qreg && !quadword_dividend) 877 | strcat(realname, "L"); 878 | if (rreg == qreg && !quadword_dividend) 879 | sprintf(buf2, "D%d", qreg); 880 | else 881 | sprintf(buf2, "D%d:D%d", rreg, qreg); 882 | 883 | if (getea(buf1, reg, mode, LONGWORD)) 884 | return; 885 | instprint(ops2f(2) | size2f(LONGWORD), realname, buf1, buf2); 886 | 887 | valid = 1; 888 | } 889 | 890 | void 891 | opa(const char *name, word_t inst) 892 | { 893 | int addrreg = (inst >> 9) & 7; 894 | int reg = inst & 7; 895 | int mode = (inst >> 3) & 7; 896 | int size = ((inst >> 8) & 1) ? LONGWORD : WORD; 897 | 898 | if (getea(buf1, reg, mode, size)) 899 | return; 900 | sprintf(buf2, "%2.2s", Areg(addrreg)); 901 | instprint(ops2f(2) | size2f(size), name, buf1, buf2); 902 | 903 | valid = 1; 904 | } 905 | 906 | void 907 | opx(const char *name, word_t inst, int mode, int printsize) 908 | { 909 | int destreg = (inst >> 9) & 7; 910 | int srcreg = inst & 7; 911 | int size = (inst >> 6) & 3; 912 | int lflags = ops2f(2); 913 | 914 | if (printsize) 915 | lflags |= size2f(size); 916 | 917 | if (inst & 8) { 918 | if (getea(buf1, srcreg, mode, size)) 919 | return; 920 | if (getea(buf2, destreg, mode, size)) 921 | return; 922 | } else { 923 | sprintf(buf1, "D%d", srcreg); 924 | sprintf(buf2, "D%d", destreg); 925 | } 926 | instprint(lflags, name, buf1, buf2); 927 | 928 | valid = 1; 929 | } 930 | 931 | void 932 | exg(word_t inst, char c1, char c2) 933 | { 934 | int reg1 = (inst >> 9) & 7; 935 | int reg2 = inst & 7; 936 | char s[2]; 937 | 938 | Areg2(buf1, c1, reg1); 939 | Areg2(buf2, c2, reg2); 940 | instprint(ops2f(2), "EXG", buf1, buf2); 941 | 942 | valid = 1; 943 | } 944 | 945 | void 946 | bitfield(word_t inst) 947 | { 948 | int reg = inst & 7; 949 | int mode = (inst >> 3) & 7; 950 | int type = (inst >> 8) & 3; 951 | long value; 952 | int failure; 953 | #ifndef OLD 954 | int destreg; 955 | int offset; 956 | int width; 957 | #else 958 | int destreg = (value >> 12) & 7; 959 | int offset = (value >> 6) & 0x1f; 960 | int width = value & 0x1f; 961 | #endif 962 | char name[10]; 963 | int n; 964 | 965 | value = getval(WORD, &failure); 966 | if (failure) 967 | return; 968 | #ifndef OLD 969 | if (value & 0x8000) 970 | return; 971 | if ((type & 1) == 0 && (value & 0xf000)) 972 | #else 973 | if ((type & 1) && (value & 0xf000)) 974 | #endif 975 | return; 976 | #ifndef OLD 977 | destreg = (value >> 12) & 7; 978 | offset = (value >> 6) & 0x1f; 979 | width = value & 0x1f; 980 | #endif 981 | sprintf(name, "BF%s", (type & 1) ? bitf[type] : bitd[type]); 982 | 983 | if (!ISDIRECT(mode)) 984 | if (name[2] == 'C' || name[2] == 'I' || name[2] == 'S') { 985 | /* BFCHG, BFCLR, BFINS, BFSET */ 986 | if (!ISACEA(mode, reg)) 987 | return; 988 | } else { 989 | /* BFEXTS, BFEXTU, BFFFO, BFTST */ 990 | if (!ISCEA(mode, reg)) 991 | return; 992 | } 993 | 994 | if (getea(buf1, reg, mode, BYTE /* actually unsized */)) 995 | return; 996 | strcpy(buf3, "{"); 997 | n = 1; 998 | if (value & 0x0800) { 999 | if (offset & ~7) 1000 | return; 1001 | n += sprintf(buf3 + n, "D%d", offset & 7); 1002 | } else 1003 | n += sprintf(buf3 + n, "%d", offset); 1004 | if (value & 0x0020) { 1005 | if (width & ~7) 1006 | return; 1007 | n += sprintf(buf3 + n, "D%d", width & 7); 1008 | } else 1009 | n += sprintf(buf3 + n, "%d", width ? width : 32); 1010 | strcat(buf3, "}"); 1011 | strcat(buf1, buf3); 1012 | if (type & 1) { 1013 | sprintf(buf2, "D%d", destreg); 1014 | instprint(ops2f(2), name, buf1, buf2); 1015 | } else 1016 | instprint(ops2f(1), name, buf1); 1017 | 1018 | valid = 1; 1019 | } 1020 | 1021 | void 1022 | getshiftname(char *name, int type, int direction) 1023 | { 1024 | switch (type) { 1025 | case 0: strcpy(name, "AS"); break; 1026 | case 1: strcpy(name, "LS"); break; 1027 | case 2: strcpy(name, "ROX"); break; 1028 | case 3: strcpy(name, "RO"); break; 1029 | } 1030 | strcat(name, direction ? "L" : "R"); 1031 | } 1032 | 1033 | void 1034 | shift(word_t inst) 1035 | { 1036 | int reg; 1037 | int mode; 1038 | int type; 1039 | int direction = (inst >> 8) & 1; 1040 | int data; 1041 | int size; 1042 | char name[10]; 1043 | 1044 | reg = inst & 7; 1045 | if ((size = ((inst >> 6) & 3)) == 3) { 1046 | size = WORD; 1047 | mode = (inst >> 3) & 7; 1048 | 1049 | if (inst & 0x0800) 1050 | return; 1051 | if (!ISAMEA(mode, reg)) 1052 | return; 1053 | 1054 | if (getea(buf1, reg, mode, size)) 1055 | return; 1056 | type = (inst >> 9) & 3; 1057 | getshiftname(name, type, direction); 1058 | instprint(ops2f(1), name, buf1); 1059 | } else { 1060 | sprintf(buf2, "D%d", reg); 1061 | type = (inst >> 3) & 3; 1062 | if (inst & 0x0020) 1063 | sprintf(buf1, "D%d", (inst >> 9) & 7); 1064 | else { 1065 | if ((data = (inst >> 9) & 7) == 0) 1066 | data = 8; 1067 | sprintf(buf1, "#%d", data); 1068 | } 1069 | getshiftname(name, type, direction); 1070 | instprint(ops2f(2) | size2f(size), name, buf1, buf2); 1071 | } 1072 | 1073 | valid = 1; 1074 | } 1075 | 1076 | void 1077 | cpsave(const char *prefix, word_t inst) 1078 | { 1079 | int reg = inst & 7; 1080 | int mode = (inst >> 3) & 7; 1081 | 1082 | if (!ISACEAplusPRE(mode, reg)) 1083 | return; 1084 | if (getea(buf1, reg, mode, BYTE /* actually unsized */)) 1085 | return; 1086 | sprintf(buf2, "%sSAVE", prefix); 1087 | instprint(ops2f(1), buf2, buf1); 1088 | 1089 | valid = 1; 1090 | } 1091 | 1092 | void 1093 | cprestore(const char *prefix, word_t inst) 1094 | { 1095 | int reg = inst & 7; 1096 | int mode = (inst >> 3) & 7; 1097 | 1098 | if (!ISCEAplusPOST(mode, reg)) 1099 | return; 1100 | if (getea(buf1, reg, mode, BYTE /* actually unsized */)) 1101 | return; 1102 | sprintf(buf2, "%sRESTORE", prefix); 1103 | instprint(ops2f(1), buf2, buf1); 1104 | 1105 | valid = 1; 1106 | } 1107 | 1108 | void 1109 | cpdbcc(struct cp *cpptr, word_t inst) 1110 | { 1111 | int reg = inst & 7; 1112 | long value; 1113 | int failure; 1114 | char sdbcc[6]; 1115 | addr_t savedpc; 1116 | short f = ops2f(2); 1117 | unsigned condition; 1118 | char *condstr; 1119 | 1120 | savedpc = pc; 1121 | condition = getval(WORD, &failure) & 0xffff; 1122 | if (failure) 1123 | return; 1124 | if (condition & 0xffc0) 1125 | return; 1126 | if ((condstr = cpptr->cc(condition)) == NULL) 1127 | return; 1128 | sprintf(sdbcc, "%sDB%s", cpptr->prefix, condstr); 1129 | sprintf(buf1, "D%d", reg); 1130 | 1131 | value = getval(WORD, &failure); 1132 | if (failure) 1133 | return; 1134 | 1135 | if (pass == FIRSTPASS && onepass != INCONSISTENT) { 1136 | required[flags & 3] = value + savedpc; 1137 | flags++; 1138 | } else if (pass == LASTPASS && value + savedpc >= initialpc 1139 | && value + savedpc <= initialpc + maxoffset 1140 | && insts[value + savedpc - initialpc].labelnum) 1141 | sprintf(buf2, "L%d", 1142 | insts[value + savedpc - initialpc].labelnum); 1143 | else /* if (pass == DEBUGPASS 1144 | || value + savedpc > initialpc + maxoffset) */ 1145 | /* immsprintf(buf2, value); */ 1146 | sprintf(buf2, "%lx", (long)(value + savedpc)); 1147 | instprint(f, sdbcc, buf1, buf2); 1148 | 1149 | valid = 1; 1150 | } 1151 | 1152 | void 1153 | cpbcc(struct cp *cpptr, word_t inst) 1154 | { 1155 | unsigned condition = inst & 0x003f; 1156 | long value; 1157 | int failure; 1158 | char sbcc[5]; 1159 | addr_t savedpc; 1160 | int size = (inst & 0x0040) ? LONGWORD : WORD; 1161 | char *condstr; 1162 | 1163 | if ((condstr = cpptr->cc(condition)) == NULL) 1164 | return; 1165 | sprintf(sbcc, "%sB%s", cpptr->prefix, condstr); 1166 | 1167 | savedpc = pc; 1168 | value = getval(size, &failure); 1169 | if (failure) 1170 | return; 1171 | 1172 | if (cpptr->prefix[0] == 'F' && cpptr->prefix[1] == '\0' 1173 | && inst == 0xf280 && value == 0) { 1174 | instprint(ops2f(0), "FNOP"); 1175 | valid = 1; 1176 | return; 1177 | } 1178 | 1179 | if (onepass != INCONSISTENT 1180 | && (value < 0 && -value > savedpc - initialpc 1181 | || value > 0 && value + savedpc > initialpc + maxoffset 1182 | || !odd && value & 1)) 1183 | return; 1184 | 1185 | if (pass == FIRSTPASS && onepass != INCONSISTENT) { 1186 | required[flags & 3] = value + savedpc; 1187 | flags++; 1188 | } else if (pass == LASTPASS && value + savedpc >= initialpc 1189 | && value + savedpc <= initialpc + maxoffset 1190 | && insts[value + savedpc - initialpc].labelnum) 1191 | sprintf(buf1, "L%d", 1192 | insts[value + savedpc - initialpc].labelnum); 1193 | else /* if (pass == DEBUGPASS 1194 | || value + savedpc > initialpc + maxoffset) */ 1195 | /* immsprintf(buf1, value); */ 1196 | sprintf(buf1, "%lx", (long)(value + savedpc)); 1197 | instprint(ops2f(1), sbcc, buf1); 1198 | 1199 | valid = 1; 1200 | } 1201 | 1202 | void 1203 | cptrapcc(struct cp *cpptr, word_t inst) 1204 | { 1205 | unsigned long value; 1206 | int failure; 1207 | int lflags; 1208 | int mode = inst & 7; 1209 | unsigned condition; 1210 | char *condstr; 1211 | 1212 | condition = getval(WORD, &failure) & 0xffff; 1213 | if (failure) 1214 | return; 1215 | if (condition & 0xffc0) 1216 | return; 1217 | if ((condstr = cpptr->cc(condition)) == NULL) 1218 | return; 1219 | sprintf(buf1, "%sTRAP%s", cpptr->prefix, condstr); 1220 | 1221 | switch (mode) { 1222 | case 2: 1223 | value = getval(WORD, &failure); 1224 | if (failure) 1225 | return; 1226 | lflags = ops2f(1) | size2f(WORD) | sharp2f(1); 1227 | break; 1228 | case 3: 1229 | value = getval(LONGWORD, &failure); 1230 | if (failure) 1231 | return; 1232 | lflags = ops2f(1) | size2f(LONGWORD) | sharp2f(1); 1233 | break; 1234 | case 4: 1235 | lflags = ops2f(0); 1236 | break; 1237 | default: 1238 | return; 1239 | } 1240 | 1241 | sprintf(buf2, "%ld", value); 1242 | 1243 | instprint(lflags, buf1, buf2); 1244 | 1245 | valid = 1; 1246 | } 1247 | 1248 | void 1249 | cpscc(struct cp *cpptr, word_t inst) 1250 | { 1251 | int reg = inst & 7; 1252 | int mode = (inst >> 3) & 7; 1253 | long value; 1254 | int failure; 1255 | unsigned condition; 1256 | char *condstr; 1257 | 1258 | if (!ISADEA(mode, reg)) 1259 | return; 1260 | condition = getval(WORD, &failure) & 0xffff; 1261 | if (failure) 1262 | return; 1263 | if ((condstr = cpptr->cc(condition)) == NULL) 1264 | return; 1265 | 1266 | if (getea(buf2, reg, mode, BYTE)) 1267 | return; 1268 | 1269 | sprintf(buf1, "%sS%s", cpptr->prefix, condstr); 1270 | instprint(ops2f(1) | sharp2f(2), buf1, buf2); 1271 | 1272 | valid = 1; 1273 | } 1274 | --------------------------------------------------------------------------------