@ -1,33 +1,382 @@
use std ::prelude ;
use std ::fmt ;
use std ::ops ::* ;
use std ::ops ::* ;
const debug : bool = true ;
fn main ( ) {
fn main ( ) {
println ! ( "Hello World!" ) ;
let mut cpu = Cpu ::new ( ) ;
let mut s = Vec ::new ( ) ;
let program :Vec < u16 > = vec ! [ 9 , 32768 , 32769 , 'a' as u16 , 19 , 32768 ] ;
s . push ( 9 ) ;
cpu . write_program ( program ) ;
println ! ( "{}" , s . pop ( ) . unwrap ( ) ) ;
let mut result = cpu . execute ( ) ;
if result . is_ok ( ) {
println ! ( "Execution successful!" ) ;
} else {
println ! ( "Err: {}" , result . err ( ) . unwrap ( ) )
}
}
}
struct Cpu {
pub struct Cpu {
stack : Vec < u16 > ,
stack : Vec < u16 > ,
mem : Vec < u16 > ,
mem : Vec < u16 > ,
reg : Vec < u16 > ,
reg : Vec < u16 > ,
pc : Number ,
pc : Number ,
alu : Alu ,
}
impl fmt ::Debug for Cpu {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
write ! ( f , "Cpu {{ pc = {}, " , self . pc . value ) ? ;
write ! ( f , "reg = " ) ? ;
for i in 0 . . 7 {
write ! ( f , "[{}]: {}, " , i , self . reg [ i ] ) ;
}
write ! ( f , "stack = " ) ? ;
for i in 0 . . self . stack . len ( ) {
write ! ( f , "[{}]: {}, " , i , self . stack [ i ] ) ? ;
}
for i in 0 . . self . mem . len ( ) {
write ! ( f , "[{}]: {}, " , i , self . mem [ i ] ) ? ;
}
write ! ( f , "}}" ) ? ;
Ok ( ( ) )
}
}
}
impl Cpu {
impl Cpu {
fn new ( ) -> Cpu {
pub fn new ( ) -> Cpu {
Cpu {
Cpu {
stack : Vec ::new ( ) ,
stack : Vec ::new ( ) ,
mem : Vec ::with_capacity ( 32768 ) ,
mem : vec ! [ 0 ; 32768 ] ,
reg : Vec ::with_capacity ( 8 ) ,
reg : vec ! [ 0 ; 8 ] ,
pc : Number ::new ( ) ,
pc : Number ::new ( ) ,
alu : Alu ::new ( ) ,
}
}
pub fn write_program ( & mut self , prog : Vec < u16 > ) {
self . pc . value = 0 ;
for i in prog {
self . mem [ self . pc . value as usize ] = i ;
self . pc . inc ( ) ;
}
self . pc . value = 0 ;
}
pub fn execute ( & mut self ) -> Result < & 'static str , & 'static str > {
let mut running = true ;
let mut err = 0 ;
if self . mem . is_empty ( ) {
running = false ;
err = 2 ;
}
while running {
match self . read ( self . pc . value ) . unwrap ( ) {
0 = > { //halt: stop execution and terminate the program
if debug {
println ! ( "{}: halt" , self . pc ) ;
}
running = false ;
} ,
1 = > { //set <a> <b>: set register <a> to the value of <b>
if debug {
println ! ( "{}: set {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let reg = self . mem [ ( self . pc . value ) as usize ] ;
self . pc . inc ( ) ;
let val = self . read ( self . pc . value ) . unwrap ( ) ;
self . write ( reg + 32768 , val ) ;
self . pc . inc ( ) ;
} ,
2 = > { //push <a>: push <a> onto the stack
if debug {
println ! ( "{}: push {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let val = self . read ( self . pc . value ) . unwrap ( ) ;
self . stack . push ( val ) ;
self . pc . inc ( ) ;
} ,
3 = > { //pop <a>: remove the top element from the stack and write it into <a>; empty stack = error
if debug {
println ! ( "{}: pop {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] ) ;
}
self . pc . inc ( ) ;
match self . stack . pop ( ) {
None = > {
running = false ;
err = 1 ;
} ,
Some ( i ) = > {
let addr = self . read ( self . pc . value ) . unwrap ( ) ;
self . write ( addr , i ) ;
self . pc . inc ( ) ;
} ,
}
} ,
4 = > { //eq <a> <b> <c>: set <a> to 1 if <b> is equal to <c>; set it to 0 otherwise
if debug {
println ! ( "{}: eq {} {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] , self . mem [ ( self . pc . value + 3 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let resaddr = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . a . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . b . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . alu . op = 0 ; //alu eq
self . alu . execute ( ) ;
let result = self . alu . c . value ;
self . write ( resaddr , result ) ;
self . pc . inc ( ) ;
} ,
5 = > { //gt <a> <b> <c>: set <a> to 1 if <b> is greater than <c>; set it to 0 otherwise
if debug {
println ! ( "{}: gt {} {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] , self . mem [ ( self . pc . value + 3 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let resaddr = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . a . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . b . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . alu . op = 1 ; //alu gt
self . alu . execute ( ) ;
let result = self . alu . c . value ;
self . write ( resaddr , result ) ;
self . pc . inc ( ) ;
} ,
6 = > { //jmp <a>: jump to <a>
if debug {
println ! ( "{}: jmp {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let target = self . read ( self . pc . value ) . unwrap ( ) ;
self . jump ( target ) ;
} ,
7 = > { //jt <a> <b>: if <a> is nonzero, jump to <b>
if debug {
println ! ( "{}: jt {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] ) ;
}
self . pc . inc ( ) ;
self . alu . a . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . alu . b . value = 0 ;
self . alu . op = 0 ; //alu op: eq
self . alu . execute ( ) ;
self . pc . inc ( ) ;
let target = self . read ( self . pc . value ) . unwrap ( ) ;
match self . alu . c . value {
0 = > { self . jump ( target ) ; } ,
_ = > { self . pc . inc ( ) ; } ,
}
} ,
8 = > { //jf <a> <b>: if <a> is zero, jump to <b>
if debug {
println ! ( "{}: jf {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] ) ;
}
self . pc . inc ( ) ;
self . alu . a . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . alu . b . value = 0 ;
self . alu . op = 0 ; //alu op: eq
self . alu . execute ( ) ;
self . pc . inc ( ) ;
let target = self . read ( self . pc . value ) . unwrap ( ) ;
match self . alu . c . value {
0 = > { self . pc . inc ( ) ; } ,
_ = > { self . jump ( target ) ; } ,
}
} ,
9 . . . 13 = > { //aluop <a> <b> <c>: compute result in alu with <a> = <b> op <c>
if debug {
println ! ( "{}: aluop {} {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] , self . mem [ ( self . pc . value + 3 ) as usize ] ) ;
}
self . alu . op = self . read ( self . pc . value ) . unwrap ( ) - 7 ; //alu ops: 2...6
self . pc . inc ( ) ;
let resaddr = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . a . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . b . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . alu . execute ( ) ;
let result = self . alu . c . value ;
self . write ( resaddr , result ) ;
self . pc . inc ( ) ;
} ,
14 = > { //not <a> <b>: stores 15-bit bitwise inverse of <b> in <a>
if debug {
println ! ( "{}: not {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let resaddr = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . alu . a . value = self . read ( self . pc . value ) . unwrap ( ) ;
self . alu . op = 7 ; //alu op: not
self . alu . execute ( ) ;
let result = self . alu . c . value ;
self . write ( resaddr , result ) ;
self . pc . inc ( ) ;
} ,
15 = > { //rmem <a> <b>: read memory at address <b> and write it to <a>
if debug {
println ! ( "{}: rmem {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let resaddr = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
let result = self . read ( self . read ( self . pc . value ) . unwrap ( ) ) . unwrap ( ) ;
self . write ( resaddr , result ) ;
self . pc . inc ( ) ;
} ,
16 = > { //wmem <a> <b>: write the value from <b> into memory at address <a>
if debug {
println ! ( "{}: wmem {} {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] , self . mem [ ( self . pc . value + 2 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let resaddr = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
let result = self . read ( self . read ( self . pc . value ) . unwrap ( ) ) . unwrap ( ) ;
self . write ( resaddr , result ) ;
self . pc . inc ( ) ;
} ,
17 = > { //call <a>: write the address of the next instruction to the stack and jump to <a>
if debug {
println ! ( "{}: call {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] ) ;
}
self . pc . inc ( ) ;
let target = self . read ( self . pc . value ) . unwrap ( ) ;
self . pc . inc ( ) ;
self . stack . push ( self . pc . value ) ;
self . jump ( target ) ;
} ,
18 = > { //ret: remove the top element from the stack and jump to it; empty stack = halt
if debug {
println ! ( "{}: ret" , self . pc ) ;
}
match self . stack . pop ( ) {
None = > {
running = false ;
} ,
Some ( target ) = > {
self . jump ( target ) ;
} ,
}
} ,
19 = > { //out <a>: write the character represented by ascii code <a> to the terminal
if debug {
println ! ( "{}: out {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] ) ;
}
self . pc + = Number { value : 1 } ;
let addr = self . read ( self . pc . value ) . unwrap ( ) ;
let c :char = self . read ( addr ) . unwrap ( ) as u8 as char ;
print ! ( "{}" , c ) ;
self . pc + = Number { value : 1 } ;
} ,
20 = > { //in <a>: read a character from the terminal and write its ascii code to <a>; it can be assumed that once input starts, it will continue until a newline is encountered; this means that you can safely read whole lines from the keyboard and trust that they will be fully read
if debug {
println ! ( "{}: in {}" , self . pc , self . mem [ ( self . pc . value + 1 ) as usize ] ) ;
}
running = false ;
} ,
21 = > { //noop: no operation
if debug {
println ! ( "{}: noop" , self . pc ) ;
}
self . pc + = Number { value : 1 }
} ,
_ = > { //invalid
if debug {
println ! ( "{}: invalid" , self . pc ) ;
}
err = 3 ;
running = false ;
}
}
}
match err {
0 = > Ok ( "Execution successful" ) ,
1 = > Err ( "Stack Empty" ) ,
2 = > Err ( "No Program" ) ,
3 = > Err ( "Invalid Instruction" ) ,
_ = > Err ( "Unknown Error" ) ,
}
}
fn read ( & self , address : u16 ) -> Option < u16 > {
match address {
0 . . . 32767 = > Some ( self . mem [ address as usize ] ) ,
32768 . . . 32775 = > Some ( self . mem [ ( address - 32768 ) as usize ] ) ,
_ = > None
}
}
fn write ( & mut self , address : u16 , val : u16 ) -> Result < u16 , & 'static str > {
match address {
0 . . . 32767 = > {
self . mem [ address as usize ] = val ;
Ok ( val )
} ,
32768 . . . 32775 = > {
self . mem [ ( address - 32768 ) as usize ] = val ;
Ok ( val )
}
_ = > Err ( "Write: Invalid address" )
}
}
fn jump ( & mut self , target : u16 ) -> Result < u16 , & 'static str > {
match target {
0 . . . 32767 = > {
self . pc . value = target ;
Ok ( target )
} ,
_ = > Err ( "Jump: Invalid address" )
}
}
}
struct Alu {
op : u16 ,
a : Number ,
b : Number ,
c : Number ,
}
impl Alu {
fn new ( ) -> Alu {
Alu {
op : 0 ,
a : Number { value : 0 } ,
b : Number { value : 0 } ,
c : Number { value : 0 } ,
}
}
fn execute ( & mut self ) {
match self . op {
0 = > self . c = Number { //eq
value : match self . a . value = = self . b . value {
true = > 1 ,
false = > 0 ,
}
} ,
1 = > self . c = Number { //gt
value : match self . a . value > self . b . value {
true = > 1 ,
false = > 0 ,
}
} ,
2 = > self . c = self . a + self . b , //add
3 = > self . c = self . a * self . b , //mult
4 = > self . c = self . a % self . b , //mod
5 = > self . c = self . a & self . b , //and
6 = > self . c = self . a | self . b , //or
7 = > self . c = ! self . a , //not
_ = > self . c = self . a , //other
}
}
}
}
}
}
//15Bit numbers for the ALU
//15Bit numbers for the ALU
#[ derive(Eq, PartialEq, Copy, Clone) ]
#[ derive(Copy, Clone, Debug ) ]
struct Number {
struct Number {
value : u16 ,
value : u16 ,
}
}
@ -42,6 +391,13 @@ impl Add for Number {
}
}
}
}
impl AddAssign for Number {
fn add_assign ( & mut self , other : Number ) {
self . value + = other . value ;
self . value % = 32768 ;
}
}
impl Sub for Number {
impl Sub for Number {
type Output = Number ;
type Output = Number ;
fn sub ( self , other : Number ) -> Number {
fn sub ( self , other : Number ) -> Number {
@ -60,31 +416,74 @@ impl Mul for Number {
}
}
}
}
impl Rem for Number {
type Output = Number ;
fn rem ( self , other : Number ) -> Number {
Number {
value : ( self . value % other . value ) ,
}
}
}
impl BitOr for Number {
type Output = Number ;
fn bitor ( self , other : Number ) -> Number {
Number {
value : ( self . value | other . value ) ,
}
}
}
impl BitAnd for Number {
type Output = Number ;
fn bitand ( self , other : Number ) -> Number {
Number {
value : ( self . value & other . value ) ,
}
}
}
impl Not for Number {
impl Not for Number {
type Output = Number ;
type Output = Number ;
fn not ( self ) -> Number {
fn not ( self ) -> Number {
Number {
Number {
value : ( ! self . value ) % 32768 ,
value : ( ! self . value ) & 0x7FFF ,
}
}
}
}
}
}
impl fmt ::Display for Number {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
write ! ( f , "{}" , self . value )
}
}
impl Number {
impl Number {
//little Endian ->
//little Endian -> memory management
fn new ( ) -> Number {
fn new ( ) -> Number {
Number {
Number {
value : 0 ,
value : 0 ,
}
}
}
}
fn get_first_byte ( & self ) -> u8 {
fn inc ( & mut self ) {
( self . value & 0xFF ) as u8
self . value + = 1 ;
}
fn get_second_byte ( & self ) -> u8 {
( ( self . value > > 8 ) & 0x7F ) as u8
}
}
fn set_bytes ( & mut self , first : u8 , second : u8 ) {
}
let mut newval :u16 = ( second & 0x7F ) as u16 ;
newval < < = 8 ;
#[ cfg(test) ]
self . value = newval + ( first as u16 ) ;
mod tests {
use super ::* ;
#[ test ]
fn nop_out_halt ( ) {
let mut cpu = Cpu ::new ( ) ;
let program : Vec < u16 > = vec ! [ 21 , 21 , 19 , 5 , 0 , 'a' as u16 ] ;
cpu . write_program ( program ) ;
let mut result = cpu . execute ( ) ;
if result . is_ok ( ) {
println ! ( "Execution successful!" ) ;
} else {
println ! ( "Err: {}" , result . err ( ) . unwrap ( ) )
}
assert ! ( result . is_ok ( ) ) ;
}
}
}
}