mirror of
https://github.com/DoctorWkt/pdp7-unix.git
synced 2026-04-15 16:19:44 +00:00
I've imported the tool changes I made in my H compiler. Also,
Anders Magnusson contributed the lrs simulation code for a7out.
This commit is contained in:
80
tools/a7out
80
tools/a7out
@@ -304,11 +304,13 @@ sub simulate {
|
||||
# If this is a breakpoint, stop now and get a user command
|
||||
if ( defined( $Breakpoint{$PC} ) ) {
|
||||
$singlestep = 1;
|
||||
dprintf( "break at PC %s\n", addr($PC) );
|
||||
printf( "break at PC %s\n", addr($PC) )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
}
|
||||
get_user_command() if ($singlestep);
|
||||
dprintf( "PC %-20.20s L.AC %d.%06o MQ %06o: ", addr($PC),
|
||||
($LINK ? 1 : 0), $AC & 0777777, $MQ );
|
||||
printf( "PC %-20.20s L.AC %d.%06o MQ %06o: ", addr($PC),
|
||||
($LINK ? 1 : 0), $AC & 0777777, $MQ )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
|
||||
#dprintf("PC %06o: instr %06o, op %03o, in %o, addr %06o indaddr %06o\n",
|
||||
# $PC, $instruction, $opcode, $indirect, $addr, $indaddr );
|
||||
@@ -345,7 +347,8 @@ sub dump_memory {
|
||||
# Load AC
|
||||
sub lac {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "lac %s (value %06o) into AC\n", addr($indaddr), $Mem[$indaddr] );
|
||||
printf( "lac %s (value %06o) into AC\n", addr($indaddr), $Mem[$indaddr] )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
$AC = $Mem[$indaddr];
|
||||
$PC++;
|
||||
}
|
||||
@@ -353,13 +356,15 @@ sub lac {
|
||||
# Deposit AC
|
||||
sub dac {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "dac AC (value %06o) into %s\n", $AC, addr($indaddr) );
|
||||
printf( "dac AC (value %06o) into %s\n", $AC, addr($indaddr) )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
|
||||
# Catch writes below the process' memory range
|
||||
if ($indaddr < 010000 && !($indaddr >= 010 && $indaddr <= 020) ) {
|
||||
$singlestep = 1;
|
||||
dprintf("(****WRITE TO LOW MEMORY****)\n");
|
||||
dprintf( "break at PC %s\n", addr($PC) );
|
||||
dprintf("(****WRITE TO LOW MEMORY 0%o ****)\n", $indaddr);
|
||||
printf( "break at PC %s\n", addr($PC) )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
}
|
||||
$Mem[$indaddr] = $AC;
|
||||
$PC++;
|
||||
@@ -368,8 +373,9 @@ sub dac {
|
||||
# Add to AC, twos complement
|
||||
sub tad {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "tad AC (value %06o) with addr %s (%06o)\n",
|
||||
$AC, addr($indaddr), $Mem[$indaddr] );
|
||||
printf( "tad AC (value %06o) with addr %s (%06o)\n",
|
||||
$AC, addr($indaddr), $Mem[$indaddr] )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
$AC = $AC + $Mem[$indaddr];
|
||||
$LINK = ( $LINK ^ $AC ) & LINKMASK;
|
||||
$AC = $AC & MAXINT;
|
||||
@@ -379,8 +385,9 @@ sub tad {
|
||||
# Add to AC, ones complement
|
||||
sub add {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "add AC (value %06o) with addr %s (%06o)\n",
|
||||
$AC, addr($indaddr), $Mem[$indaddr] );
|
||||
printf( "add AC (value %06o) with addr %s (%06o)\n",
|
||||
$AC, addr($indaddr), $Mem[$indaddr] )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
|
||||
# This logic shamelessly borrowed from SimH
|
||||
# https://github.com/simh/simh/blob/master/PDP18B/pdp18b_cpu.c
|
||||
@@ -398,8 +405,9 @@ sub add {
|
||||
# And AC and Y
|
||||
sub and {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "and AC (value %06o) with addr %s (%06o)\n",
|
||||
$AC, addr($indaddr), $Mem[$indaddr] );
|
||||
printf( "and AC (value %06o) with addr %s (%06o)\n",
|
||||
$AC, addr($indaddr), $Mem[$indaddr] )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
$AC &= $Mem[$indaddr];
|
||||
$PC++;
|
||||
}
|
||||
@@ -416,14 +424,21 @@ sub xor {
|
||||
# Skip if AC different to Y
|
||||
sub sad {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "sad %s (%06o)\n", addr($indaddr), $Mem[$indaddr] );
|
||||
printf( "sad %s (%06o)\n", addr($indaddr), $Mem[$indaddr] )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
if ($AC != $Mem[$indaddr]) {
|
||||
dprintf( " adding 2 to PC\n");
|
||||
} else {
|
||||
dprintf( " adding 1 to PC\n");
|
||||
}
|
||||
$PC += ( $AC != $Mem[$indaddr] ) ? 2 : 1;
|
||||
}
|
||||
|
||||
# Deposit zero in memory
|
||||
sub dzm {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "dzm %s\n", addr($indaddr) );
|
||||
printf( "dzm %s\n", addr($indaddr) )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
$Mem[$indaddr] = 0;
|
||||
$PC++;
|
||||
}
|
||||
@@ -431,7 +446,8 @@ sub dzm {
|
||||
# Index and skip if zero
|
||||
sub isz {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "isz %s (value %06o)\n", addr($indaddr), $Mem[$indaddr] );
|
||||
printf( "isz %s (value %06o)\n", addr($indaddr), $Mem[$indaddr] )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
$Mem[$indaddr]++;
|
||||
$Mem[$indaddr] &= MAXINT;
|
||||
$PC += ( $Mem[$indaddr] == 0 ) ? 2 : 1;
|
||||
@@ -440,14 +456,16 @@ sub isz {
|
||||
# Jump
|
||||
sub jmp {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "jmp %s\n", addr($indaddr) );
|
||||
printf( "jmp %s\n", addr($indaddr) )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
$PC = $indaddr;
|
||||
}
|
||||
|
||||
# Jump to subroutine
|
||||
sub jms {
|
||||
my ( $instruction, $addr, $indaddr ) = @_;
|
||||
dprintf( "jms %s\n", addr($indaddr) );
|
||||
printf( "jms %s\n", addr($indaddr) )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
|
||||
# Save the LINK and current PC into the $indaddr location
|
||||
$Mem[ $indaddr++ ] = $PC + 1 | ( ($LINK) ? 0400000 : 0 );
|
||||
@@ -594,7 +612,7 @@ sub eae {
|
||||
dprintf( "idiv %06o by %06o (decimal %d by %d)\n",
|
||||
$AC, $divisor, $AC, $divisor );
|
||||
# Prevent division by zero :-)
|
||||
my $quotient = ($divisor) ? $AC / $divisor : 0;
|
||||
my $quotient = ($divisor) ? int($AC / $divisor) : 0;
|
||||
my $remainder = ($divisor) ? $AC % $divisor : 0;
|
||||
$MQ= $quotient;
|
||||
$AC= $remainder;
|
||||
@@ -648,8 +666,11 @@ sub eae {
|
||||
$PC++;
|
||||
return;
|
||||
}
|
||||
if ( $maskedinstr == 0640600 ) { # lls: long left shift
|
||||
# lls: long left shift
|
||||
if ( ($maskedinstr == 0640600) || ($maskedinstr == 0641600) ) {
|
||||
dprintf( "lls step %d\n", $step );
|
||||
# Clear AC if the 01000 bit is set
|
||||
$AC=0 if ($maskedinstr == 0641600);
|
||||
foreach my $i ( 1 .. $step ) {
|
||||
my $MQmsb = ( $MQ & SIGN ) ? 1 : 0;
|
||||
$AC = ( ( $AC << 1 ) | $MQmsb ) & MAXINT;
|
||||
@@ -657,6 +678,19 @@ sub eae {
|
||||
}
|
||||
$PC++;
|
||||
return;
|
||||
}
|
||||
# lrs: long right shift
|
||||
if ( ($maskedinstr == 0640500) || ($maskedinstr == 0641500) ) {
|
||||
dprintf( "lrs step %d\n", $step );
|
||||
# Clear AC if the 01000 bit is set
|
||||
$AC=0 if ($maskedinstr == 0641500);
|
||||
foreach my $i ( 1 .. $step ) {
|
||||
my $MQmsb = ( $AC & 1 ) ? 0400000 : 0;
|
||||
$AC = ( ( $AC >> 1 ) | ( ($LINK) ? 0400000 : 0 ) ) & MAXINT;
|
||||
$MQ = ( ( $MQ >> 1 ) | $MQmsb ) & MAXINT;
|
||||
}
|
||||
$PC++;
|
||||
return;
|
||||
}
|
||||
if ( $maskedinstr == 0640700 ) { # als: AC left shift
|
||||
dprintf( "als AC step %d\n", $step );
|
||||
@@ -1021,7 +1055,8 @@ sub sys_read {
|
||||
my $count = $Mem[ $PC + 2 ];
|
||||
my $end = ( $start + $count - 1 ) & MAXADDR;
|
||||
die("sys_read: bad start/end addresses $start $end\n") if ( $end < $start );
|
||||
dprintf( "read: %d words into %s from fd %d\n", $count, addr($start), $fd );
|
||||
printf( "read: %d words into %s from fd %d\n", $count, addr($start), $fd )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
|
||||
# Bump up the PC
|
||||
$PC += 3;
|
||||
@@ -1086,7 +1121,8 @@ sub sys_write {
|
||||
my $end = ( $start + $count - 1 ) & MAXADDR;
|
||||
die("sys_write: bad start/end addresses $start $end\n")
|
||||
if ( $end < $start );
|
||||
dprintf( "write: %d words from %s to fd %d\n", $count, addr($start), $fd );
|
||||
printf( "write: %d words from %s to fd %d\n", $count, addr($start), $fd )
|
||||
if ( ($debug) || ($singlestep) );
|
||||
|
||||
# Bump up the PC
|
||||
$PC += 3;
|
||||
|
||||
@@ -132,6 +132,7 @@ usage() if ( @ARGV < 1 );
|
||||
div => 0640323, # divide
|
||||
norm => 0640444, # normalize, unsigned
|
||||
lls => 0640600, # long left shift
|
||||
clls => 0641600, # lls but clear AC first
|
||||
als => 0640700, # AC shift
|
||||
lrs => 0640500, # long right shift
|
||||
lacs => 0641001, # load AC with SC
|
||||
@@ -195,6 +196,7 @@ usage() if ( @ARGV < 1 );
|
||||
# lam => 0777777, # (load accumulator minus)
|
||||
);
|
||||
|
||||
|
||||
# Parse all the files
|
||||
print STDERR "I\n"; # like the real as
|
||||
foreach my $file (@ARGV) {
|
||||
@@ -342,7 +344,7 @@ sub parse_line {
|
||||
|
||||
print "parse_line: '$line'\n" if ($debug);
|
||||
|
||||
while ($line =~ s{^([A-Za-z0-9\.]+):\s*}{}) { # labels
|
||||
while ($line =~ s{^([A-Za-z0-9_\.]+):\s*}{}) { # labels
|
||||
process_label($1);
|
||||
}
|
||||
|
||||
@@ -440,9 +442,10 @@ sub parse_expression {
|
||||
print "\tfound >x\n" if ($debug);
|
||||
$syllable = ord($1) # absolute
|
||||
}
|
||||
elsif ($line =~ s{^([A-Za-z\.][A-Za-z0-9\.]*)}{}) {
|
||||
elsif ($line =~ s{^([A-Za-z\.][A-Za-z0-9_\.]*)}{}) {
|
||||
my $sym = $1;
|
||||
print "\tsym: $sym\n" if ($debug);
|
||||
|
||||
if (defined($Var{$sym})) {
|
||||
$syllable = $Var{$sym};
|
||||
printf("\tvar: %s: %#o\n", $sym, $syllable) if ($debug);
|
||||
|
||||
Reference in New Issue
Block a user