home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.pdx.edu
/
2014.02.ftp.ee.pdx.edu.tar
/
ftp.ee.pdx.edu
/
pub
/
users
/
Harry
/
Relay
/
WardsPerlSimulator.pl
< prev
Wrap
Perl Script
|
2006-04-10
|
5KB
|
171 lines
#!/usr/bin/perl
# Interpreter (c) 2006, Ward Cunningham, released under GPL v2 or higher
# Architecture & sample code by Harry Porter
my (@r, $pc, $j, @mem, @src);
my ($z, $cy, $s);
my ($a, $b, $c, $d, $m1, $m2, $x, $y) = 0..7;
my $run = 1;
my $alu;
sub i8 {
return substr($_[0],0,1)*128 +
substr($_[0],1,1)*64 +
substr($_[0],2,1)*32 +
substr($_[0],3,1)*16 +
substr($_[0],4,1)*8 +
substr($_[0],5,1)*4 +
substr($_[0],6,1)*2 +
substr($_[0],7,1)
}
sub i5 {
return substr($_[0],0,1)*(16+32+64+128) +
substr($_[0],1,1)*8 +
substr($_[0],2,1)*4 +
substr($_[0],3,1)*2 +
substr($_[0],4,1);
}
sub r3 {return substr($_[0],0,1)*4 + substr($_[0],1,1)*2 + substr($_[0],2,1);}
sub r2 {return substr($_[0],1,1)*2 + substr($_[0],2,1);}
sub pc2 {return $mem[$pc++]*256 + $mem[$pc++];}
sub b2 {return (($_[0]>>8)%256, $_[0]%256);}
sub xy {return $r[6]*256 + $r[7];}
sub alu {
$z = $_[0]%256==0;
$cy = $_[0]>=256;
$s = $_[0]%256>=128;
$alu=sprintf("%08b",$_[0]%256);
return $_[0]%256
}
for (<DATA>) {
chomp;
s/¼/~/g;
next unless /(\s*[01]){16}/;
my ($a, $b, $c, $d) = /([01]{4})/g;
$mem[i8("$a$b")] = i8("$c$d");
$src[i8("$a$b")] = pack("A60",$_);
}
@r[$x, $y] = (221, 179);
fetch:
print $src[$pc];
$_ = sprintf ('%08b', $mem[$pc++]);
execute:
goto clear_ if /00(...)\1/;
goto move_ if /00(...)(...)/;
goto set_8_ if /01(.)(.....)/;
goto add_ if /1000(.)000/;
goto inc_ if /1000(.)001/;
goto and_ if /1000(.)010/;
goto or_ if /1000(.)011/;
goto xor_ if /1000(.)100/;
goto not_ if /1000(.)101/;
goto shift_ if /1000(.)110/;
goto load_ if /10010.(..)/;
goto store_ if /10011.(..)/;
goto incxy_ if /10110000/;
goto ret_ if /10100010/;
goto halt_ if /10101110/;
goto goto_ if /11100110/;
goto call_ if /11100111/;
goto branch_ if /111....0/;
goto set_16_ if /11....../;
die "bad op: $_\n";
clear_: $r[r3($1)] = 0; goto trace;
move_: $r[r3($1)] = $r[r3($2)]; goto trace;
set_8_: $r[$1?$b:$a] = i5($2); goto trace;
add_: $r[$1?$d:$a] = alu($r[$b] + $r[$c]); goto trace;
inc_: $r[$1?$d:$a] = alu($r[$b] + 1); goto trace;
and_: $r[$1?$d:$a] = alu($r[$b] & $r[$c]); goto trace;
or_: $r[$1?$d:$a] = alu($r[$b] | $r[$c]); goto trace;
xor_: $r[$1?$d:$a] = alu($r[$b] ^ $r[$c]); goto trace;
not_: $r[$1?$d:$a] = alu(~($r[$b])); goto trace;
shift_: $r[$1?$d:$a] = alu($r[$b] << 1); goto trace;
load_: $r[r2($1)] = $mem[pc2()]; goto trace;
store_: $mem[pc2()] = $r[r2($1)]; goto trace;
incxy_: @r[$x..$y] = b2(xy()+1); goto trace;
ret_: $pc = xy(); goto trace;
halt_: $pc = 0; $run=0; goto trace;
goto_:;
call_:;
branch_:;
set_16_:
@r[$m1..$m2] = b2(pc2()) if /110...../;
$j = pc2() if /111...../;
@r[$x..$y] = b2($pc) if /11.....1/;
$pc = $j if /11.1..../ and $s;
$pc = $j if /11..1.../ and !$cy;
$pc = $j if /11...1../ and $z;
$pc = $j if /11....1./ and !$z;
goto trace;
trace:
#print map(sprintf('[%08b]',$_),@r);
print "$alu\n";
$alu = "";
goto fetch if $run;
__DATA__
0000 0000 0010 1110 M2=X M2 = X
0000 0001 0101 1001 A=-7 D = -7
0000 0010 0001 1000 D=A .
0000 0011 0110 0000 B=0 if sign(y)==0
0000 0100 0001 0111 C=Y .
0000 0101 1000 0011 A=B|C .
0000 0110 1111 0000 BNEG Loop .
0000 0111 0000 0000 . .
0000 1000 0000 1010 . .
0000 1001 0010 1001 M2=B M2 = 0
0000 1010 0000 1100 Loop: B=M1 LOOP:
0000 1011 1000 0110 A=B<<1 Shift M1 left
0000 1100 0001 0000 C=A . (noncircular)
0000 1101 0111 1110 B=1111,1110 .
0000 1110 1000 0010 A=B&C .
0000 1111 0010 0000 M1=A .
0001 0000 0000 1101 B=M2 if sign(M2)==1
0001 0001 1000 0101 A=¼B .
0001 0010 1111 0000 BNEG Lab1 .
0001 0011 0000 0000 . .
0001 0100 0001 1000 . .
0001 0101 0000 1100 B=M1 M1 = M1 + 1
0001 0110 1000 0001 A=B+1 .
0001 0111 0010 0000 M1=A .
0001 1000 0000 1101 Lab1: B=M2 Shift M2 left
0001 1001 1000 0110 A=B<<1 . (noncircular)
0001 1010 0001 0000 C=A .
0001 1011 0111 1110 B=1111,1110 .
0001 1100 1000 0010 A=B&C .
0001 1101 0010 1000 M2=A .
0001 1110 0000 1111 B=Y shift Y left
0001 1111 1000 0110 A=B<<1 .
0010 0000 0011 1000 Y=A .
0010 0001 0000 1111 B=Y if sign(Y)=1
0010 0010 1000 0101 A=¼B .
0010 0011 1111 0000 BNEG Lab2 .
0010 0100 0000 0000 . .
0010 0101 0011 0000 . .
0010 0110 0000 1101 B=M2 M2 = M2 + X
0010 0111 0001 0110 C=X .
0010 1000 1000 0000 A=B+C .
0010 1001 0010 1000 M2=A .
0010 1010 1110 1000 BNC Lab2 if carry
0010 1011 0000 0000 . .
0010 1100 0011 0000 . .
0010 1101 0000 1100 B=M1 M1 = M1 + 1
0010 1110 1000 0001 A=B+1 .
0010 1111 0010 0000 M1=A .
0011 0000 0000 1011 Lab2: B=D D = D + 1
0011 0001 1000 1001 D=B+1 .
0011 0010 1110 0010 BNZ Loop if D != 0
0011 0011 0000 0000 . . goto Loop
0011 0100 0000 1010 . .
0011 0101 1010 1110 HALT Halt