1
0
mirror of https://github.com/wfjm/w11.git synced 2026-01-27 12:52:27 +00:00
Files
wfjm.w11/tools/bin/ldadump
2019-08-02 23:34:18 +02:00

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";
}