#!/usr/bin/perl # Interpreter (c) 2006, Ward Cunningham, released under GPL v2 or higher # Architecture & sample code by Harry Porter print "Content-Type: text/html\n\n"; my (@r, $pc, $j, @mem, @src); my ($z, $cy, $s); my ($a, $b, $c, $d, $m1, $m2, $x, $y) = 0..7; my @reg = ('a', 'b', 'c', 'd', 'm1', 'm2', 'x', 'y'); my $run = 1; my $cycles; my $alu; read (STDIN, $_, $ENV{CONTENT_LENGTH}); my ($arg, %arg); for (split(/&/, $_)) { s/\+/ /g; s/\%(..)/pack('C', hex($1))/geo; ($_, $arg) = split (/=/, $_, 2); $arg{$_} = $arg; } print <<"";
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("%04b %04b",$_[0]/16%16,$_[0]%16); $alu = "$alu"; return $_[0]%256 } for (split(/\n/, $arg{mem})) { s/\r|\n//g; 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 and $cycles++ < 10000; __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