Add to git.
[dlife.git] / dlife_disasm.pl
1 #!/usr/bin/perl -w
2
3 # DLIFE disassembler.
4 # By Richard W.M. Jones.
5 #
6 # $Id: dlife_disasm.pl,v 1.1 2002/04/05 14:40:26 rich Exp $
7
8 use strict;
9
10 use Getopt::Long;
11
12 my $help;
13
14 GetOptions ("help|?" => \$help);
15
16 if ($help)
17   {
18     printf STDERR "dlife_disasm.pl [--help] [file.dlo] > file.dla\n";
19     exit 1;
20   }
21
22 # Read the entire input file into memory so that we can do some
23 # clever stuff with string regexes.
24 my $code = "";
25
26 while (<>)
27   {
28     $code .= $_;
29   }
30
31 # Remove anything which isn't [0-9a-f].
32 $code =~ tr/0-9a-fA-F//cd;
33 $code =~ tr/a-f/A-F/;
34
35 # Convert code to <xx>.
36 $code =~ s/(..)/<$1>/g;
37
38 # NOTE: The order of this substitutions IS important.
39
40 # CALLB and CALLF macros.
41 $code =~ s/<23>(<08>|<09>)((<00>|<01>)+)<22><27>/convert_call ($1, $2)/ge;
42
43 # JMPB and JMPF macros.
44 $code =~ s/(<08>|<09>)((<00>|<01>)+)<22><27>/convert_jmp ($1, $2)/ge;
45
46 # JMPBZ and JMPFZ macros.
47 $code =~ s/(<08>|<09>)((<00>|<01>)+)<22><07><27><26>/convert_jmpz ($1, $2)/ge;
48
49 # Basic FINDF and FINDB commands.
50 $code =~ s/(<08>|<09>)((<00>|<01>)+)/convert_find ($1, $2)/ge;
51
52 # Any other patterns are labels.
53 $code =~ s/((<00>|<01>)+)/convert_label ($1)/ge;
54
55 # MOVE macro.
56 $code =~ s/(<2[0-3]>)(<2[4-7]>)/convert_move ($1, $2)/ge;
57
58 # SWAP macro. XXX Difficult ...
59
60
61
62
63
64
65
66 print $code;
67
68 sub convert_call
69   {
70     my $find_code = shift;
71     my $pattern = shift;
72
73     my $insn = $find_code eq "<08>" ? "CALLB" : "CALLF";
74
75     $pattern =~ s/<00>/1/g;     # Pattern is complemented.
76     $pattern =~ s/<01>/0/g;
77
78     return "\n\t$insn ~$pattern\n";
79   }
80
81 sub convert_jmp
82   {
83     my $find_code = shift;
84     my $pattern = shift;
85
86     my $insn = $find_code eq "<08>" ? "JMPB" : "JMPF";
87
88     $pattern =~ s/<00>/1/g;     # Pattern is complemented.
89     $pattern =~ s/<01>/0/g;
90
91     return "\n\t$insn ~$pattern\n";
92   }
93
94 sub convert_jmpz
95   {
96     my $find_code = shift;
97     my $pattern = shift;
98
99     my $insn = $find_code eq "<08>" ? "JMPBZ" : "JMPFZ";
100
101     $pattern =~ s/<00>/1/g;     # Pattern is complemented.
102     $pattern =~ s/<01>/0/g;
103
104     return "\n\t$insn ~$pattern\n";
105   }
106
107 sub convert_find
108   {
109     my $find_code = shift;
110     my $pattern = shift;
111
112     my $insn = $find_code eq "<08>" ? "FINDB" : "FINDF";
113
114     $pattern =~ s/<00>/1/g;     # Pattern is complemented.
115     $pattern =~ s/<01>/0/g;
116
117     return "\n\t$insn ~$pattern\n";
118   }
119
120 sub convert_label
121   {
122     my $pattern = shift;
123
124     $pattern =~ s/<00>/0/g;
125     $pattern =~ s/<01>/1/g;
126
127     return "\n$pattern:\n";
128   }
129
130 sub convert_move
131   {
132     my $push_code = shift;
133     my $pop_code = shift;
134
135     my ($src, $dst);
136     if ($push_code eq "<20>") { $src = "A" }
137     elsif ($push_code eq "<21>") { $src = "B" }
138     elsif ($push_code eq "<22>") { $src = "I" }
139     elsif ($push_code eq "<23>") { $src = "P" }
140     if ($pop_code eq "<24>") { $dst = "A" }
141     elsif ($pop_code eq "<25>") { $dst = "B" }
142     elsif ($pop_code eq "<26>") { $dst = "I" }
143     elsif ($pop_code eq "<27>") { $dst = "P" }
144
145     return "\n\tMOVE $src,$dst\n";
146   }
147