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   
Perl Script  |  2006-04-10  |  5KB  |  171 lines

  1. #!/usr/bin/perl
  2. # Interpreter (c) 2006, Ward Cunningham, released under GPL v2 or higher
  3. # Architecture & sample code by Harry Porter
  4.  
  5. my (@r, $pc, $j, @mem, @src);
  6. my ($z, $cy, $s);
  7. my ($a, $b, $c, $d, $m1, $m2, $x, $y) = 0..7;
  8. my $run = 1;
  9. my $alu;
  10.  
  11. sub i8    {
  12.     return     substr($_[0],0,1)*128 + 
  13.         substr($_[0],1,1)*64 + 
  14.         substr($_[0],2,1)*32 + 
  15.         substr($_[0],3,1)*16 + 
  16.         substr($_[0],4,1)*8 + 
  17.         substr($_[0],5,1)*4 + 
  18.         substr($_[0],6,1)*2 + 
  19.         substr($_[0],7,1)
  20. }
  21.  
  22. sub i5    {
  23.     return     substr($_[0],0,1)*(16+32+64+128) + 
  24.         substr($_[0],1,1)*8 + 
  25.         substr($_[0],2,1)*4 + 
  26.         substr($_[0],3,1)*2 + 
  27.         substr($_[0],4,1);
  28. }
  29.  
  30. sub r3    {return substr($_[0],0,1)*4 + substr($_[0],1,1)*2 + substr($_[0],2,1);}
  31. sub r2    {return substr($_[0],1,1)*2 + substr($_[0],2,1);}
  32. sub pc2 {return $mem[$pc++]*256 + $mem[$pc++];}
  33. sub b2     {return (($_[0]>>8)%256, $_[0]%256);}
  34. sub xy    {return $r[6]*256 + $r[7];}
  35.  
  36. sub alu {
  37.     $z = $_[0]%256==0; 
  38.     $cy = $_[0]>=256; 
  39.     $s = $_[0]%256>=128; 
  40.     $alu=sprintf("%08b",$_[0]%256); 
  41.     return $_[0]%256
  42. }
  43.  
  44. for (<DATA>) {
  45.     chomp;
  46.     s/¼/~/g;
  47.     next unless /(\s*[01]){16}/;
  48.     my ($a, $b, $c, $d) = /([01]{4})/g;
  49.     $mem[i8("$a$b")] = i8("$c$d");
  50.     $src[i8("$a$b")] = pack("A60",$_);
  51. }
  52.  
  53. @r[$x, $y] = (221, 179);
  54.  
  55. fetch:
  56.     print $src[$pc];
  57.     $_ = sprintf ('%08b', $mem[$pc++]);
  58.  
  59. execute:
  60.     goto clear_     if /00(...)\1/;
  61.     goto move_     if /00(...)(...)/;
  62.     goto set_8_    if /01(.)(.....)/;
  63.     goto add_    if /1000(.)000/;
  64.     goto inc_    if /1000(.)001/;
  65.     goto and_    if /1000(.)010/;
  66.     goto or_    if /1000(.)011/;
  67.     goto xor_    if /1000(.)100/;
  68.     goto not_    if /1000(.)101/;
  69.     goto shift_    if /1000(.)110/;
  70.     goto load_    if /10010.(..)/;
  71.     goto store_    if /10011.(..)/;
  72.     goto incxy_    if /10110000/;
  73.     goto ret_    if /10100010/;
  74.     goto halt_    if /10101110/;
  75.     goto goto_    if /11100110/;
  76.     goto call_    if /11100111/;
  77.     goto branch_    if /111....0/;
  78.     goto set_16_    if /11....../;
  79.     die "bad op: $_\n";
  80.  
  81. clear_:    $r[r3($1)] = 0;                goto trace;
  82. move_:    $r[r3($1)] = $r[r3($2)];        goto trace;
  83. set_8_:    $r[$1?$b:$a] = i5($2);            goto trace;
  84. add_:    $r[$1?$d:$a] = alu($r[$b] + $r[$c]);    goto trace;
  85. inc_:    $r[$1?$d:$a] = alu($r[$b] + 1);     goto trace;
  86. and_:    $r[$1?$d:$a] = alu($r[$b] & $r[$c]);     goto trace;
  87. or_:    $r[$1?$d:$a] = alu($r[$b] | $r[$c]);     goto trace;
  88. xor_:    $r[$1?$d:$a] = alu($r[$b] ^ $r[$c]);     goto trace;
  89. not_:    $r[$1?$d:$a] = alu(~($r[$b]));         goto trace;
  90. shift_:    $r[$1?$d:$a] = alu($r[$b] << 1);     goto trace;
  91. load_:    $r[r2($1)] = $mem[pc2()];        goto trace;
  92. store_:    $mem[pc2()] = $r[r2($1)];        goto trace;
  93. incxy_:    @r[$x..$y] = b2(xy()+1);        goto trace;
  94. ret_:    $pc = xy();                goto trace;
  95. halt_:    $pc = 0; $run=0;            goto trace;
  96.  
  97. goto_:;
  98. call_:;
  99. branch_:;
  100. set_16_:
  101.     @r[$m1..$m2] = b2(pc2())    if /110...../;
  102.     $j = pc2()            if /111...../;
  103.     @r[$x..$y] = b2($pc)        if /11.....1/;
  104.     $pc = $j            if /11.1..../ and $s;
  105.     $pc = $j            if /11..1.../ and !$cy;
  106.     $pc = $j            if /11...1../ and $z;
  107.     $pc = $j            if /11....1./ and !$z;
  108.     goto trace;
  109.         
  110. trace:
  111.     #print map(sprintf('[%08b]',$_),@r);
  112.     print "$alu\n";
  113.     $alu = "";
  114.     goto fetch if $run;
  115.     
  116.  
  117. __DATA__
  118. 0000 0000   0010 1110   M2=X      M2 = X 
  119. 0000 0001   0101 1001   A=-7      D = -7 
  120. 0000 0010   0001 1000   D=A       . 
  121. 0000 0011   0110 0000   B=0       if sign(y)==0 
  122. 0000 0100   0001 0111   C=Y       . 
  123. 0000 0101   1000 0011   A=B|C     . 
  124. 0000 0110   1111 0000   BNEG Loop . 
  125. 0000 0111   0000 0000   .         . 
  126. 0000 1000   0000 1010   .         . 
  127. 0000 1001   0010 1001   M2=B        M2 = 0 
  128. 0000 1010   0000 1100 Loop: B=M1  LOOP: 
  129. 0000 1011   1000 0110   A=B<<1      Shift M1 left 
  130. 0000 1100   0001 0000   C=A         . (noncircular) 
  131. 0000 1101   0111 1110   B=1111,1110 . 
  132. 0000 1110   1000 0010   A=B&C       . 
  133. 0000 1111   0010 0000   M1=A        . 
  134. 0001 0000   0000 1101   B=M2        if sign(M2)==1 
  135. 0001 0001   1000 0101   A=¼B        . 
  136. 0001 0010   1111 0000   BNEG Lab1   . 
  137. 0001 0011   0000 0000   .           . 
  138. 0001 0100   0001 1000   .           . 
  139. 0001 0101   0000 1100   B=M1          M1 = M1 + 1 
  140. 0001 0110   1000 0001   A=B+1         . 
  141. 0001 0111   0010 0000   M1=A          . 
  142. 0001 1000   0000 1101 Lab1: B=M2    Shift M2 left
  143. 0001 1001   1000 0110   A=B<<1      . (noncircular) 
  144. 0001 1010   0001 0000   C=A         . 
  145. 0001 1011   0111 1110   B=1111,1110 . 
  146. 0001 1100   1000 0010   A=B&C       . 
  147. 0001 1101   0010 1000   M2=A        . 
  148. 0001 1110   0000 1111   B=Y         shift Y left 
  149. 0001 1111   1000 0110   A=B<<1      . 
  150. 0010 0000   0011 1000   Y=A         . 
  151. 0010 0001   0000 1111   B=Y         if sign(Y)=1 
  152. 0010 0010   1000 0101   A=¼B        . 
  153. 0010 0011   1111 0000   BNEG Lab2   . 
  154. 0010 0100   0000 0000   .           . 
  155. 0010 0101   0011 0000   .           . 
  156. 0010 0110   0000 1101   B=M2          M2 = M2 + X 
  157. 0010 0111   0001 0110   C=X           . 
  158. 0010 1000   1000 0000   A=B+C         . 
  159. 0010 1001   0010 1000   M2=A          . 
  160. 0010 1010   1110 1000   BNC Lab2      if carry 
  161. 0010 1011   0000 0000   .             . 
  162. 0010 1100   0011 0000   .             . 
  163. 0010 1101   0000 1100   B=M1            M1 = M1 + 1 
  164. 0010 1110   1000 0001   A=B+1           . 
  165. 0010 1111   0010 0000   M1=A            . 
  166. 0011 0000   0000 1011 Lab2: B=D     D = D + 1 
  167. 0011 0001   1000 1001   D=B+1       . 
  168. 0011 0010   1110 0010   BNZ Loop    if D != 0 
  169. 0011 0011   0000 0000   .           .  goto Loop 
  170. 0011 0100   0000 1010   .           . 
  171. 0011 0101   1010 1110   HALT        Halt