diff --git a/projects/07/MemoryAccess/BasicTest/BasicTest.asm b/projects/07/MemoryAccess/BasicTest/BasicTest.asm new file mode 100644 index 0000000..4a8a9fa --- /dev/null +++ b/projects/07/MemoryAccess/BasicTest/BasicTest.asm @@ -0,0 +1,224 @@ +@10 // push constant 10 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 10 +@SP // pop +A=M-1 +D=M +@LCL +A=M // Read @LCL to A +M=D // Write D to *A +@21 // push constant 21 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 21 +@22 // push constant 22 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 22 +@ARG // argument 2 +D=M +@2 // write 2 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @ARG+2 to R13 +@SP // pop +A=M-1 +D=M +@R13 +A=M // Read @R13 to A +M=D // Write D to *A +@ARG // argument 1 +D=M +@1 // write 1 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @ARG+1 to R13 +@SP // pop +A=M-1 +D=M +@R13 +A=M // Read @R13 to A +M=D // Write D to *A +@36 // push constant 36 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 36 +@THIS // this 6 +D=M +@6 // write 6 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @THIS+6 to R13 +@SP // pop +A=M-1 +D=M +@R13 +A=M // Read @R13 to A +M=D // Write D to *A +@42 // push constant 42 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 42 +@45 // push constant 45 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 45 +@THAT // that 5 +D=M +@5 // write 5 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @THAT+5 to R13 +@SP // pop +A=M-1 +D=M +@R13 +A=M // Read @R13 to A +M=D // Write D to *A +@THAT // that 2 +D=M +@2 // write 2 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @THAT+2 to R13 +@SP // pop +A=M-1 +D=M +@R13 +A=M // Read @R13 to A +M=D // Write D to *A +@510 // push constant 510 +D=A +@SP +A=M +M=D +@SP +M=M+1 // end push constant 510 +@LCL // local 0 +D=M +@0 // write 0 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @LCL+0 to R13 +@R13 +D=M +@SP +A=M +M=D +@SP +M=M+1 // end push local 0 +@THAT // that 5 +D=M +@5 // write 5 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @THAT+5 to R13 +@R13 +D=M +@SP +A=M +M=D +@SP +M=M+1 // end push that 5 +@SP // ==== add ==== +A=M-1 +D=M +A=A-1 +M=D+M +@SP +M=M-1 +@ARG // argument 1 +D=M +@1 // write 1 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @ARG+1 to R13 +@R13 +D=M +@SP +A=M +M=D +@SP +M=M+1 // end push argument 1 +@SP // ==== sub ==== +A=M-1 +D=M +A=A-1 +M=M-D +@SP +M=M-1 +@THIS // this 6 +D=M +@6 // write 6 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @THIS+6 to R13 +@R13 +D=M +@SP +A=M +M=D +@SP +M=M+1 // end push this 6 +@THIS // this 6 +D=M +@6 // write 6 to A +D=D+A // D = segment+index +@R13 // save it to R13 +M=D // write @THIS+6 to R13 +@R13 +D=M +@SP +A=M +M=D +@SP +M=M+1 // end push this 6 +@SP // ==== add ==== +A=M-1 +D=M +A=A-1 +M=D+M +@SP +M=M-1 +@SP // ==== sub ==== +A=M-1 +D=M +A=A-1 +M=M-D +@SP +M=M-1 +@R11 // temp 6 +D=M +@SP +A=M +M=D +@SP +M=M+1 // end push temp 6 +@SP // ==== add ==== +A=M-1 +D=M +A=A-1 +M=D+M +@SP +M=M-1 +@223 +0;JMP diff --git a/projects/07/MemoryAccess/BasicTest/BasicTest.out b/projects/07/MemoryAccess/BasicTest/BasicTest.out new file mode 100644 index 0000000..240f194 --- /dev/null +++ b/projects/07/MemoryAccess/BasicTest/BasicTest.out @@ -0,0 +1,2 @@ +|RAM[256]|RAM[300]|RAM[401]|RAM[402]|RAM[3006|RAM[3012|RAM[3015|RAM[11] | +| 10 | 10 | 22 | 22 | 36 | 45 | 45 | 0 | diff --git a/vm/VMTranslator.php b/vm/VMTranslator.php index c5cbcd1..5434d98 100644 --- a/vm/VMTranslator.php +++ b/vm/VMTranslator.php @@ -216,19 +216,94 @@ class CodeWriter { "@$index // push $segment $index", // Write it to D "D=A", - // A=SP - "@SP", - "A=M", - // Write D to SP - "M=D", - // Bump Stack Pointer - "@SP", - "M=M+1 // end push $segment $index", + ]); + break; + case 'argument': + case 'local': + case 'this': + case 'that': + $this->resolveSegmentToR13($segment, $index); + $this->write([ + "@R13", + "D=M", + ]); + break; + + case 'temp': + // Temp section starts from R5; + $tempBase = 5; + $ramAddress = $tempBase + $index; + $register = "@R$ramAddress"; + $this->write([ + "$register // temp $index", + "D=M" ]); break; default: - throw new Exception("Not Implemented $segment", 1); + throw new \Exception("Not Implemented $segment", 1); + break; + } + + $this->write([ + // A=SP + "@SP", + "A=M", + // Write D to SP + "M=D", + // Bump Stack Pointer + "@SP", + "M=M+1 // end push $segment $index", + ]); + } + + private function segmentToRegister(String $segment) { + return [ + 'local' => '@LCL', + 'argument' => '@ARG', + 'this' => '@THIS', + 'that' => '@THAT', + ][$segment]; + } + + private function resolveSegmentToR13(string $segment, Int $index) { + $register = $this->segmentToRegister($segment); + $this->write([ + "$register // $segment $index" , + "D=M", + "@$index // write $index to A", + "D=D+A // D = segment+index", + "@R13 // save it to R13", + "M=D // write $register+$index to R13", + ]); + } + + private function writePop(String $segment, Int $index) { + switch ($segment) { + // The address is given by LCL+INDEX + case 'local': + case 'argument': + case 'this': + case 'that': + if($index !== 0) { + $this->resolveSegmentToR13($segment, $index); + $lookupRegister = '@R13'; + } else { + $lookupRegister = $this->segmentToRegister($segment); + } + + $this->write([ + "@SP // pop", + "A=M-1", + "D=M", + $lookupRegister, + "A=M // Read $lookupRegister to A", + "M=D // Write D to *A", + ]); + break; + + default: + # code... break; } } @@ -240,7 +315,7 @@ class CodeWriter { break; case CommandType::POP: - + $this->writePop($segment, $index); break; default: throw new Exception("Invalid Command Type", 1);