4 # By Richard W.M. Jones.
6 # $Id: dlife_asm.pl,v 1.1 2002/04/05 14:40:26 rich Exp $
14 GetOptions ("help|?" => \$help);
18 print STDERR "dlife_asm.pl [--help] file.dla [file.dla [...]]\n";
22 # Read input file(s) and assemble each one. Each input file has the
23 # form ``filename.dla'' and we will write a file called ``filename.dlo''.
24 foreach my $filename (@ARGV)
26 my $output = $filename . ".dlo";
28 if ($filename =~ m/(.*)\.dla$/)
30 $output = $1 . ".dlo";
33 open FILE, "<$filename" or die "$filename: $!";
34 open OUT, ">$output" or die "$output: $!";
38 # Remove terminating CRs and LFs.
41 # Ignore blank lines and comments.
46 # Parse the instruction.
59 # Trim leading and trailing whitespace.
60 $insn =~ s/^[ \t]+//g;
61 $insn =~ s/[ \t]+$//g;
64 if ($insn =~ m/^([01]+):(.*)$/)
69 foreach (split //, $label)
71 if (m/0/) { print OUT "00" }
72 if (m/1/) { print OUT "01" }
79 # IFZ instruction prefix?
80 if ($insn =~ m/^IFZ[ \t]+(.*)$/i)
90 elsif ($insn =~ m/^$/)
95 elsif ($insn =~ m/^NOP0$/i)
99 elsif ($insn =~ m/^NOP1$/i)
103 elsif ($insn =~ m/^INC[ \t]+A$/i)
107 elsif ($insn =~ m/^DEC[ \t]+A$/i)
111 elsif ($insn =~ m/^SHL[ \t]+A$/i)
115 elsif ($insn =~ m/^FINDB[ \t](.*)$/i)
120 elsif ($insn =~ m/^FINDF[ \t](.*)$/i)
125 elsif ($insn =~ m/^MALLOC$/i)
129 elsif ($insn =~ m/^DIVIDE$/i)
133 elsif ($insn =~ m/^MOVE[ \t]+\[I\],A$/i)
137 elsif ($insn =~ m/^MOVE[ \t]+A,\[I\]$/i)
141 elsif ($insn =~ m/^DMOVE[ \t]+\[I\],A$/i)
145 elsif ($insn =~ m/^DMOVE[ \t]+A,\[I\]$/i)
149 elsif ($insn =~ m/^XOR[ \t]+([ABIP]),([ABIP])$/i)
151 my $reg1 = reg2bin ($1);
152 my $reg2 = reg2bin ($2);
154 printf OUT ("%02X\n", 16 + ($reg2 << 2) + $reg1);
156 elsif ($insn =~ m/^PUSH[ \t]+([ABIP])$/i)
158 my $reg = reg2bin ($1);
160 printf OUT ("%02X\n", 32 + $reg);
162 elsif ($insn =~ m/^POP[ \t]+([ABIP])$/i)
164 my $reg = reg2bin ($1);
166 printf OUT ("%02X\n", 36 + $reg);
168 # Instruction set macros.
169 elsif ($insn =~ m/MOVE[ \t]+([ABIP]),([ABIP])$/i)
171 my $reg1 = reg2bin ($1);
172 my $reg2 = reg2bin ($2);
174 printf OUT ("%02X", 32 + $reg1); # PUSH reg1
175 printf OUT ("%02X\n", 36 + $reg2); # POP reg2
177 elsif ($insn =~ m/SWAP[ \t]+([ABIP]),([ABIP])$/i)
179 my $reg1 = reg2bin ($1);
180 my $reg2 = reg2bin ($2);
182 printf OUT ("%02X", 16 + ($reg2 << 2) + $reg1); # XOR reg1, reg2
183 printf OUT ("%02X", 16 + ($reg1 << 2) + $reg2); # XOR reg2, reg1
184 printf OUT ("%02X", 16 + ($reg2 << 2) + $reg1); # XOR reg1, reg2
185 printf OUT ("%02X\n", 16 + ($reg1 << 2) + $reg2); # XOR reg2, reg1
187 elsif ($insn =~ m/ZERO[ \t]+([ABIP])$/i)
189 my $reg = reg2bin ($1);
191 printf OUT ("%02X\n", 16 + ($reg << 2) + $reg); # XOR reg, reg
193 elsif ($insn =~ m/ADD[ \t]+([0-9]+),A$/i)
197 for (my $i = 0; $i < $n; ++$i)
203 elsif ($insn =~ m/MOVE[ \t]+([0-9]+),A$/i)
207 print OUT "10"; # XOR A,A
212 print OUT "0402"; # SHL A; INC A
216 print OUT "04"; # SHL A
222 elsif ($insn =~ m/LOAD[ \t]+([0-9]+),A$/i)
226 print OUT "222124"; # PUSH I; PUSH B; POP A
227 for (my $i = 0; $i < $n * 2; ++$i)
229 print OUT "02"; # INC A
231 print OUT "20260E26\n"; # PUSH A; POP I; DMOVE [I],A; POP I
233 elsif ($insn =~ m/STORE[ \t]+A,([0-9]+)$/i)
237 print OUT "22202124"; # PUSH I; PUSH A; PUSH B; POP A
238 for (my $i = 0; $i < $n * 2; ++$i)
240 print OUT "02"; # INC A
242 print OUT "2026240F26\n"; # PUSH A; POP I; POP A; DMOVE A,[I]; POP I
244 elsif ($insn =~ m/^JMP[ \t]+I$/i)
246 print OUT "2227\n"; # PUSH I; POP P
248 elsif ($insn =~ m/^JMPF[ \t](.*)$/i)
250 print OUT "09"; # FINDF
252 print OUT "2227\n"; # PUSH I; POP P
254 elsif ($insn =~ m/^JMPB[ \t](.*)$/i)
256 print OUT "08"; # FINDB
258 print OUT "2227\n"; # PUSH I; POP P
260 elsif ($insn =~ m/^JMPZF[ \t](.*)$/i)
262 print OUT "09"; # FINDF
264 print OUT "22072726\n"; # PUSH I; IFZ POP P; POP I
266 elsif ($insn =~ m/^JMPZB[ \t](.*)$/i)
268 print OUT "08"; # FINDB
270 print OUT "22072726\n"; # PUSH I; IFZ POP P; POP I
272 elsif ($insn =~ m/^CALLF[ \t](.*)$/i)
274 print OUT "2309"; # PUSH P; FINDF
276 print OUT "2227\n"; # PUSH I; POP P
278 elsif ($insn =~ m/^CALLB[ \t](.*)$/i)
280 print OUT "2308"; # PUSH P; FINDB
282 print OUT "2227\n"; # PUSH I; POP P
284 elsif ($insn =~ m/^RET[ \t]+([0-9]+)$/i)
287 print OUT "24"; # POP A
288 for (my $i = 0; $i < $n + 3; ++$i)
290 print OUT "02"; # INC A
292 print OUT "2027\n"; # PUSH A; POP P
294 elsif ($insn =~ m/^DB[ \t]+([0-9]+)$/i)
297 for (my $i = 0; $i < $n; ++$i)
303 elsif ($insn =~ m/^DW[ \t]+([0-9]+)$/i)
306 for (my $i = 0; $i < $n * 2; ++$i)
314 die "$insn: unknown instruction";
322 if ($pattern =~ m/^([01]+)$/)
324 foreach (split //, $1)
326 if (m/0/) { print OUT "00" }
327 if (m/1/) { print OUT "01" }
330 elsif ($pattern =~ m/^~([01]+)$/) # Complemented pattern.
332 foreach (split //, $1)
334 if (m/0/) { print OUT "01" }
335 if (m/1/) { print OUT "00" }
340 die "$pattern: unrecognized pattern argument";
348 if (uc($reg) eq "A") { return 0 }
349 elsif (uc($reg) eq "B") { return 1 }
350 elsif (uc($reg) eq "I") { return 2 }
351 elsif (uc($reg) eq "P") { return 3 }
354 die "$reg: unknown register name";