mirror of
https://github.com/wfjm/w11.git
synced 2026-01-27 12:52:27 +00:00
179 lines
5.0 KiB
Perl
Executable File
179 lines
5.0 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
# $Id: ldadump 1189 2019-07-13 16:41:07Z mueller $
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# Copyright 2019- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
|
#
|
|
# Revision History:
|
|
# Date Rev Version Comment
|
|
# 2019-07-13 1189 1.0.2 drop superfluous exists for $opts
|
|
# 2019-04-19 1133 1.0.1 better -trec format of start address record
|
|
# 2019-04-13 1131 1.0 Initial version
|
|
#
|
|
#
|
|
|
|
use 5.14.0; # require Perl 5.14 or higher
|
|
use strict; # require strict checking
|
|
|
|
use Getopt::Long;
|
|
|
|
my %opts = ();
|
|
|
|
GetOptions(\%opts, "help", "lsm", "tbyt", "trec")
|
|
or bailout("bad command options");
|
|
|
|
if ($opts{help}) {
|
|
print_help();
|
|
exit 0;
|
|
}
|
|
|
|
foreach my $files (@ARGV) {
|
|
do_file($files);
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
sub do_file {
|
|
my ($file) = @_;
|
|
my $fh;
|
|
|
|
if ($file eq '-') {
|
|
$fh = *STDIN;
|
|
} else {
|
|
open($fh,'<:raw',$file) or bailout("failed to open '$file': $!");
|
|
}
|
|
|
|
my @bytes;
|
|
while (1) {
|
|
my $buf;
|
|
my $rc = read($fh, $buf, 1024);
|
|
bailout("failed to read '$file': $!") unless defined $rc;
|
|
last if $rc == 0;
|
|
push @bytes,unpack 'C*',$buf;
|
|
}
|
|
close $fh;
|
|
|
|
my $addr = 0; # current address
|
|
my $ldaddr = 0; # block load address
|
|
my $chksum = 0; # check sum
|
|
my $chrnum = -1; # char number in bock
|
|
my $blknum = 0; # char number in bock
|
|
my $bytcnt = 0; # byte count
|
|
my $state = 'chr0';
|
|
my $cstate = 'chr0';
|
|
my $caddr = 0;
|
|
|
|
my %mem;
|
|
|
|
foreach my $byte (@bytes) {
|
|
$cstate = $state;
|
|
$caddr = $addr;
|
|
$chrnum += 1;
|
|
$chksum = ($chksum + $byte) & 0xff; # 8 bit arithmetic
|
|
|
|
if ($state eq 'chr0') { # state: chr0 --------------------
|
|
if ($byte == 0) {
|
|
$chrnum = -1;
|
|
$state = 'chr0';
|
|
} elsif ($byte == 1) {
|
|
$state = 'chr1';
|
|
} else {
|
|
bailout("unexpected byte in 'chr0':" . sprintf('%3.3o',$byte));
|
|
}
|
|
|
|
} elsif ($state eq 'chr1') { # state: chr1 --------------------
|
|
if ($byte == 0) {
|
|
$state = 'cntlow';
|
|
} else {
|
|
bailout("unexpected byte in 'chr1:" . sprintf('%3.3o',$byte));
|
|
}
|
|
|
|
} elsif ($state eq 'cntlow') { # state: cntlow ------------------
|
|
$bytcnt = $byte;
|
|
$state = 'cnthgh';
|
|
|
|
} elsif ($state eq 'cnthgh') { # state: cnthgh ------------------
|
|
$bytcnt |= ($byte<<8);
|
|
$state = 'adrlow';
|
|
|
|
} elsif ($state eq 'adrlow') { # state: adrlow ------------------
|
|
$addr = $byte;
|
|
$state = 'adrhgh';
|
|
|
|
} elsif ($state eq 'adrhgh') { # state: adrhgh ------------------
|
|
$addr |= ($byte<<8);
|
|
$ldaddr = $addr;
|
|
$state = ($bytcnt == 6) ? 'chksum' : 'data';
|
|
if ($opts{trec}) {
|
|
printf "block %3d, length %4d byte, address %6.6o",
|
|
$blknum, $bytcnt-6, $ldaddr;
|
|
printf ":%6.6o", $ldaddr+($bytcnt-6)-1 if $bytcnt > 6;
|
|
printf "\n",
|
|
}
|
|
|
|
} elsif ($state eq 'data') { # state: data --------------------
|
|
my $oaddr = sprintf '%6.6o', ($addr & 0xfffe);
|
|
my $b0 = 0;
|
|
my $b1 = 0;
|
|
if (exists $mem{$oaddr}) {
|
|
$b0 = $mem{$oaddr} & 0xff;
|
|
$b1 = ($mem{$oaddr}>>8) & 0xff;
|
|
}
|
|
$b0 = $byte if ($addr & 0x1) == 0;
|
|
$b1 = $byte if ($addr & 0x1) != 0;
|
|
$mem{$oaddr} = ($b1 << 8) | $b0;
|
|
|
|
$addr += 1;
|
|
$state = ($chrnum == $bytcnt-1) ? 'chksum' : 'data';
|
|
|
|
} elsif ($state eq 'chksum') { # state: chksum ------------------
|
|
$chrnum = -1;
|
|
$blknum += 1;
|
|
$state = 'chr0';
|
|
} else { # state: BAD ---------------------
|
|
bailout("BUGCHECK: bad state '$state'");
|
|
}
|
|
if ($opts{tbyt}) {
|
|
printf "%-6s: n=%4d c=%4d cs=%3.3o a=%6.6o: %3.3o\n",
|
|
$cstate, $chrnum, $bytcnt, $chksum, $caddr, $byte;
|
|
}
|
|
last if $cstate eq 'chksum' && $bytcnt == 6;
|
|
}
|
|
|
|
bailout("unexpected EOF in state '$cstate'")
|
|
unless $cstate eq 'chksum' && $bytcnt == 6;
|
|
|
|
my $nmax = $opts{lsm} ? 1 : 8;
|
|
my $nval = 0;
|
|
$caddr = 0;
|
|
foreach my $oaddr (sort keys %mem) {
|
|
my $addr = oct($oaddr);
|
|
if ($nval >= $nmax || ($nval > 0 && $caddr != $addr)) {
|
|
print "\n";
|
|
$nval = 0;
|
|
}
|
|
printf "%s :",$oaddr if $nval == 0;
|
|
printf " %6.6o", $mem{$oaddr};
|
|
$caddr = $addr + 2;
|
|
$nval += 1;
|
|
}
|
|
print "\n" if $nval > 0;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
sub bailout {
|
|
my ($msg) = @_;
|
|
print STDERR "ldadump-F: $msg\n";
|
|
exit 1;
|
|
}
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
sub print_help {
|
|
print "usage: ldadump [opts] <file>\n";
|
|
print " --lsm dump in lsmem format\n";
|
|
print " --tbyt trace input bytes and states\n";
|
|
print " --trec trace records\n";
|
|
print " --help this message\n";
|
|
}
|