mirror of
https://github.com/DoctorWkt/pdp7-unix.git
synced 2026-01-25 19:57:20 +00:00
tools/a7out: I took out the code to pretend to deal with binary files,
and I did a perltidy to reformat the code.
This commit is contained in:
200
tools/a7out
200
tools/a7out
@@ -37,7 +37,8 @@ while ( defined( $ARGV[0] ) && ( $ARGV[0] =~ m{^-} ) ) {
|
||||
|
||||
# -d: debug mode
|
||||
if ( $ARGV[0] eq "-d" ) {
|
||||
$debug = 1; shift(@ARGV);
|
||||
$debug = 1;
|
||||
shift(@ARGV);
|
||||
}
|
||||
|
||||
# -b: set a breakpoint
|
||||
@@ -144,7 +145,7 @@ sub set_arguments {
|
||||
my $c1 = substr( $str, $i, 1 ) || "";
|
||||
my $c2 = substr( $str, $i + 1, 1 ) || "";
|
||||
|
||||
#printf("Saving %06o to %06o\n", (ord($c1) << 9 ) | ord($c2), $addr);
|
||||
#printf("Saving %06o to %06o\n", (ord($c1) << 9 ) | ord($c2), $addr);
|
||||
$Mem[ $addr++ ] = ( ord($c1) << 9 ) | ord($c2);
|
||||
}
|
||||
}
|
||||
@@ -184,15 +185,15 @@ sub simulate {
|
||||
my $indaddr = ($indirect) ? $Mem[$addr] & MAXADDR : $addr;
|
||||
|
||||
# If this is a breakpoint, stop now and get a user command
|
||||
if ( defined( $Breakpoint{$PC} ) ) {
|
||||
$singlestep = 1;
|
||||
dprintf( "break at PC %06o\n", $PC );
|
||||
}
|
||||
if ( defined( $Breakpoint{$PC} ) ) {
|
||||
$singlestep = 1;
|
||||
dprintf( "break at PC %06o\n", $PC );
|
||||
}
|
||||
get_user_command() if ($singlestep);
|
||||
dprintf( "PC %06o: ", $PC );
|
||||
|
||||
#dprintf("PC %06o: instr %06o, op %03o, in %o, addr %06o indaddr %06o\n",
|
||||
# $PC, $instruction, $opcode, $indirect, $addr, $indaddr );
|
||||
#dprintf("PC %06o: instr %06o, op %03o, in %o, addr %06o indaddr %06o\n",
|
||||
# $PC, $instruction, $opcode, $indirect, $addr, $indaddr );
|
||||
|
||||
# Simulate the instruction. Each subroutine updates the $PC
|
||||
if ( defined( $Oplist{$opcode} ) ) {
|
||||
@@ -248,25 +249,17 @@ sub add {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "add AC (value %06o) with addr %06o (%06o)\n",
|
||||
$AC, $indaddr, $Mem[$indaddr] );
|
||||
# $LINK = 0;
|
||||
# $AC = $AC + $Mem[$indaddr];
|
||||
# if ( $AC & LINKMASK ) {
|
||||
# $AC++; # End-around carry
|
||||
# $LINK = LINKMASK;
|
||||
# }
|
||||
# $AC = $AC & MAXINT;
|
||||
#
|
||||
|
||||
# This logic shamelessly borrowed from SimH
|
||||
# https://github.com/simh/simh/blob/master/PDP18B/pdp18b_cpu.c
|
||||
my $sum= $AC + $Mem[$indaddr];
|
||||
if ($sum > MAXINT) { # end around carry
|
||||
$sum = ($sum + 1) & MAXINT;
|
||||
my $sum = $AC + $Mem[$indaddr];
|
||||
if ( $sum > MAXINT ) { # end around carry
|
||||
$sum = ( $sum + 1 ) & MAXINT;
|
||||
}
|
||||
if (((~$AC ^ $sum) & ($AC ^ $sum)) & SIGN) { # overflow?
|
||||
$LINK= LINKMASK; # set link
|
||||
if ( ( ( ~$AC ^ $sum ) & ( $AC ^ $sum ) ) & SIGN ) { # overflow?
|
||||
$LINK = LINKMASK; # set link
|
||||
}
|
||||
$AC= $sum;
|
||||
|
||||
$AC = $sum;
|
||||
$PC++;
|
||||
}
|
||||
|
||||
@@ -341,8 +334,8 @@ sub opr {
|
||||
}
|
||||
|
||||
# law: load word into AC
|
||||
my $indirect = ( $instruction >> 13 ) & 1;
|
||||
if ( $indirect) {
|
||||
my $indirect = ( $instruction >> 13 ) & 1;
|
||||
if ($indirect) {
|
||||
dprintf( "law %06o into AC\n", $instruction );
|
||||
$AC = $instruction;
|
||||
$PC++;
|
||||
@@ -350,94 +343,104 @@ sub opr {
|
||||
}
|
||||
|
||||
# List of skip opcode names for the next section
|
||||
my @skipop= ( '', 'sma', 'sza', 'sza sma',
|
||||
'snl', 'snl sma', 'snl sza', 'snl sza sma',
|
||||
'skp', 'spa', 'sna', 'sna spa',
|
||||
'szl', 'szl spa', 'szl sna', 'szl sna spa');
|
||||
my @skipop = (
|
||||
'', 'sma', 'sza', 'sza sma',
|
||||
'snl', 'snl sma', 'snl sza', 'snl sza sma',
|
||||
'skp', 'spa', 'sna', 'sna spa',
|
||||
'szl', 'szl spa', 'szl sna', 'szl sna spa'
|
||||
);
|
||||
|
||||
# This logic shamelessly borrowed from SimH
|
||||
# https://github.com/simh/simh/blob/master/PDP18B/pdp18b_cpu.c
|
||||
my $skip=0;
|
||||
my $i= ($instruction >> 6) & 017; # decode IR<8:11>
|
||||
dprintf("L.AC %d.%06o %s", ($LINK) ? 1 : 0, $AC, $skipop[$i]);
|
||||
my $skip = 0;
|
||||
my $i = ( $instruction >> 6 ) & 017; # decode IR<8:11>
|
||||
dprintf( "L.AC %d.%06o %s", ($LINK) ? 1 : 0, $AC, $skipop[$i] );
|
||||
|
||||
$skip=1 if (($i == 1) && ($AC & SIGN) != 0); # sma
|
||||
$skip=1 if (($i == 2) && ($AC & MAXINT) == 0); # sza
|
||||
$skip=1 if (($i == 3) &&
|
||||
((($AC & MAXINT) == 0) || (($AC & SIGN) != 0))); # sza | sma
|
||||
$skip=1 if (($i == 4) && ($LINK)); # snl
|
||||
$skip=1 if (($i == 5) && ($LINK || ($AC >= SIGN))); # snl | sma
|
||||
$skip=1 if (($i == 6) && ($LINK || ($AC == 0))); # snl | sza
|
||||
$skip=1 if (($i == 7) &&
|
||||
($LINK || ($AC >= SIGN) || ($AC == 0))); # snl | sza | sma
|
||||
$skip=1 if ($i == 010); # skp
|
||||
$skip=1 if (($i == 011) && (($AC & SIGN) == 0)); # spa
|
||||
$skip=1 if (($i == 012) && (($AC & MAXINT) != 0)); # sna
|
||||
$skip=1 if (($i == 013) &&
|
||||
(($AC & MAXINT) != 0) && (($AC & SIGN) == 0)); # sna & spa
|
||||
$skip=1 if (($i == 014) && ($LINK == 0)); # szl
|
||||
$skip=1 if (($i == 015) && ($LINK == 0) && ($AC < SIGN)); # szl & spa
|
||||
$skip=1 if (($i == 016) && ($LINK == 0) && ($AC != 0)); # szl & sna
|
||||
$skip=1 if (($i == 017) &&
|
||||
($LINK == 0) && ($AC != 0) && ($AC != 0)); # szl & sna & spa
|
||||
$skip = 1 if ( ( $i == 1 ) && ( $AC & SIGN ) != 0 ); # sma
|
||||
$skip = 1 if ( ( $i == 2 ) && ( $AC & MAXINT ) == 0 ); # sza
|
||||
$skip = 1 if ( ( $i == 3 )
|
||||
&& ( ( ( $AC & MAXINT ) == 0 ) || ( ( $AC & SIGN ) != 0 ) ) )
|
||||
; # sza | sma
|
||||
$skip = 1 if ( ( $i == 4 ) && ($LINK) ); # snl
|
||||
$skip = 1 if ( ( $i == 5 ) && ( $LINK || ( $AC >= SIGN ) ) ); # snl | sma
|
||||
$skip = 1 if ( ( $i == 6 ) && ( $LINK || ( $AC == 0 ) ) ); # snl | sza
|
||||
$skip = 1 if ( ( $i == 7 )
|
||||
&& ( $LINK || ( $AC >= SIGN ) || ( $AC == 0 ) ) ); # snl | sza | sma
|
||||
$skip = 1 if ( $i == 010 ); # skp
|
||||
$skip = 1 if ( ( $i == 011 ) && ( ( $AC & SIGN ) == 0 ) ); # spa
|
||||
$skip = 1 if ( ( $i == 012 ) && ( ( $AC & MAXINT ) != 0 ) ); # sna
|
||||
$skip = 1 if ( ( $i == 013 )
|
||||
&& ( ( $AC & MAXINT ) != 0 )
|
||||
&& ( ( $AC & SIGN ) == 0 ) ); # sna & spa
|
||||
$skip = 1 if ( ( $i == 014 ) && ( $LINK == 0 ) ); # szl
|
||||
$skip = 1
|
||||
if ( ( $i == 015 ) && ( $LINK == 0 ) && ( $AC < SIGN ) ); # szl & spa
|
||||
$skip = 1
|
||||
if ( ( $i == 016 ) && ( $LINK == 0 ) && ( $AC != 0 ) ); # szl & sna
|
||||
$skip = 1 if ( ( $i == 017 )
|
||||
&& ( $LINK == 0 )
|
||||
&& ( $AC != 0 )
|
||||
&& ( $AC != 0 ) ); # szl & sna & spa
|
||||
|
||||
# Clear operations
|
||||
if ($instruction & 010000) { # cla
|
||||
dprintf(" cla"); $AC=0;
|
||||
if ( $instruction & 010000 ) { # cla
|
||||
dprintf(" cla"); $AC = 0;
|
||||
}
|
||||
if ($instruction & 004000) { # cli
|
||||
dprintf(" cli"); $LINK=0;
|
||||
if ( $instruction & 004000 ) { # cli
|
||||
dprintf(" cli"); $LINK = 0;
|
||||
}
|
||||
if ($instruction & 000002) { # cmi
|
||||
dprintf(" cmi"); $LINK= ($LINK) ? 0 : LINKMASK;
|
||||
if ( $instruction & 000002 ) { # cmi
|
||||
dprintf(" cmi");
|
||||
$LINK = ($LINK) ? 0 : LINKMASK;
|
||||
}
|
||||
if ($instruction & 000001) { # cma
|
||||
dprintf(" cma"); $AC= ($AC ^ MAXINT) & MAXINT;
|
||||
if ( $instruction & 000001 ) { # cma
|
||||
dprintf(" cma");
|
||||
$AC = ( $AC ^ MAXINT ) & MAXINT;
|
||||
}
|
||||
|
||||
# Rotate instructions
|
||||
$i= $instruction & 02030;
|
||||
$i = $instruction & 02030;
|
||||
|
||||
# Single rotate right
|
||||
if ($i == 020) {
|
||||
dprintf(" rar");
|
||||
if ( $i == 020 ) {
|
||||
dprintf(" rar");
|
||||
my $newlink = ( $AC & 1 ) ? LINKMASK : 0;
|
||||
$AC = ( $LINK | $AC ) >> 1;
|
||||
$LINK = $newlink;
|
||||
}
|
||||
|
||||
# Double rotate right
|
||||
if ($i == 02020) {
|
||||
dprintf(" rtr");
|
||||
my $msb= ($AC & 1) << 17;
|
||||
if ( $i == 02020 ) {
|
||||
dprintf(" rtr");
|
||||
my $msb = ( $AC & 1 ) << 17;
|
||||
my $newlink = ( $AC & 2 ) ? LINKMASK : 0;
|
||||
$AC = (( $LINK | $AC ) >> 2) | $msb;
|
||||
$AC = ( ( $LINK | $AC ) >> 2 ) | $msb;
|
||||
$LINK = $newlink;
|
||||
}
|
||||
|
||||
# Single rotate left
|
||||
if ($i == 010) {
|
||||
dprintf(" ral");
|
||||
if ( $i == 010 ) {
|
||||
dprintf(" ral");
|
||||
my $newlink = ( $AC & SIGN ) ? LINKMASK : 0;
|
||||
my $lsb = $LINK ? 1 : 0;
|
||||
$AC= (($AC << 1) | $lsb) & MAXINT;
|
||||
my $lsb = $LINK ? 1 : 0;
|
||||
$AC = ( ( $AC << 1 ) | $lsb ) & MAXINT;
|
||||
$LINK = $newlink;
|
||||
}
|
||||
|
||||
# Double rotate left
|
||||
if ($i == 02010) {
|
||||
dprintf(" rtl");
|
||||
if ( $i == 02010 ) {
|
||||
dprintf(" rtl");
|
||||
my $newlink = ( $AC & 0200000 ) ? LINKMASK : 0;
|
||||
my $lsb = ( $AC & SIGN ) ? 1 : 0;
|
||||
my $twolsb = $LINK ? 2 : 0;
|
||||
$AC= (($AC << 2) | $twolsb | $lsb) & MAXINT;
|
||||
my $lsb = ( $AC & SIGN ) ? 1 : 0;
|
||||
my $twolsb = $LINK ? 2 : 0;
|
||||
$AC = ( ( $AC << 2 ) | $twolsb | $lsb ) & MAXINT;
|
||||
$LINK = $newlink;
|
||||
}
|
||||
|
||||
# Impossible left and right rotates: 02030 or 00030. Do nothing!
|
||||
|
||||
# Note: We didn't do the oas instruction above.
|
||||
$PC+= 1 + $skip;
|
||||
$PC += 1 + $skip;
|
||||
dprintf("\n");
|
||||
return;
|
||||
}
|
||||
@@ -471,22 +474,20 @@ sub eae {
|
||||
$instruction &= EAEIMASK;
|
||||
|
||||
if ( $instruction == 0660500 ) { # lrss: long right shift, signed
|
||||
# We ignore the MQ as it's not
|
||||
# used by any user-mode programs
|
||||
# We ignore the MQ as it's not
|
||||
# used by any user-mode programs
|
||||
dprintf( "lrss %06o AC step %d\n", $AC, $step );
|
||||
|
||||
# Save the AC's sign into LINK
|
||||
my $newlink = ( $AC << 1 ) & LINKMASK;
|
||||
|
||||
$AC = (($LINK |$AC) >> $step) & MAXINT;
|
||||
$LINK= $newlink;
|
||||
$AC = ( ( $LINK | $AC ) >> $step ) & MAXINT;
|
||||
$LINK = $newlink;
|
||||
$PC++;
|
||||
return;
|
||||
}
|
||||
if ( $instruction == 0660700 ) { # alss: long left shift, signed
|
||||
# We don't fill the lsb with LINK yet
|
||||
# We don't fill the lsb with LINK yet
|
||||
dprintf( "alss %06o AC step %d\n", $AC, $step );
|
||||
|
||||
$AC = ( $AC << $step ) & MAXINT;
|
||||
$PC++;
|
||||
return;
|
||||
@@ -526,6 +527,7 @@ sub sys_close {
|
||||
|
||||
# Open system call
|
||||
sub sys_open {
|
||||
|
||||
# Open seems to have 2 arguments: PC+1 is a pointer to the filename.
|
||||
# PC+2 seems to be 1 for write, 0 for read.
|
||||
# Some programs seem to have a third argument always set to 0.
|
||||
@@ -538,7 +540,7 @@ sub sys_open {
|
||||
my $filename = mem2arg($start);
|
||||
|
||||
# Choose to open read-only or write-only
|
||||
my $readorwrite= ($Mem[ $PC + 2 ]) ? ">" : "<";
|
||||
my $readorwrite = ( $Mem[ $PC + 2 ] ) ? ">" : "<";
|
||||
dprintf( "open: base %06o, %s file %s\n", $start, $readorwrite, $filename );
|
||||
|
||||
# Bump up the PC
|
||||
@@ -595,22 +597,12 @@ sub sys_read {
|
||||
$count = 0;
|
||||
foreach my $addr ( $start .. $end ) {
|
||||
|
||||
# It's a terminal, so convert from ASCII
|
||||
if ( -t $FH ) {
|
||||
my $c1 = getc($FH);
|
||||
last if ( !defined($c1) ); # No character, leave the loop
|
||||
my $c2 = getc($FH) || ""; # No character, make it a NUL
|
||||
$Mem[$addr] =
|
||||
( ord($c1) << 9 ) | ord($c2); # Pack both into one word
|
||||
$count++;
|
||||
} else {
|
||||
# otherwise (for now) read in one line and convert to octal
|
||||
my $line = <$FH>;
|
||||
last if ( !defined($line) ); # No line, leave the loop
|
||||
chomp($line);
|
||||
$Mem[$addr] = oct($line) & MAXINT;
|
||||
$count++;
|
||||
}
|
||||
my $c1 = getc($FH);
|
||||
last if ( !defined($c1) ); # No character, leave the loop
|
||||
my $c2 = getc($FH) || ""; # No character, make it a NUL
|
||||
$Mem[$addr] =
|
||||
( ord($c1) << 9 ) | ord($c2); # Pack both into one word
|
||||
$count++;
|
||||
}
|
||||
|
||||
# No error
|
||||
@@ -647,13 +639,7 @@ sub sys_write {
|
||||
my $FH = $FD[$fd];
|
||||
foreach my $addr ( $start .. $end ) {
|
||||
|
||||
# It's a terminal, so convert to ASCII
|
||||
# otherwise (for now) print in octal
|
||||
if ( -t $FH ) {
|
||||
print( $FH word2ascii( $Mem[$addr] ) );
|
||||
} else {
|
||||
printf( $FH "%06o\n", $Mem[$addr] );
|
||||
}
|
||||
print( $FH word2ascii( $Mem[$addr] ) );
|
||||
}
|
||||
|
||||
# No error
|
||||
|
||||
Reference in New Issue
Block a user