コード例 #1
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private IEnumerable <string> ProcessEqGtLt(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            var idAfter = idgen.Id();

            yield return("@" + idAfter);

            yield return("D=A");

            switch (vmcmd.Kcmd)
            {
            case Kcmd.Eq:
                yield return("@" + lblEq);

                break;

            case Kcmd.Gt:
                yield return("@" + lblGt);

                break;

            case Kcmd.Lt:
                yield return("@" + lblLt);

                break;
            }
            yield return("D;JMP");

            yield return("(" + idAfter + ")");
        }
コード例 #2
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private IEnumerable <string> Bootstrap(Idgen idgen)
        {
            lblFunCall = idgen.Id("funcall");
            lblReturn  = idgen.Id("return");
            lblEq      = idgen.Id("eq");
            lblGt      = idgen.Id("gt");
            lblLt      = idgen.Id("lt");

            var lblEnd = idgen.Id("end");

            yield return("//SP=256");

            yield return("@256");

            yield return("D=A");

            yield return("@0");

            yield return("M=D");

            idgen.filn = "Sys.vm";
            foreach (var st in ProcessCall(new Vmcmd(Kcmd.Call, Ksegment.Nil, 0, "Sys.init"), idgen, null))
            {
                yield return(st);
            }
            idgen.filn = null;

            yield return("(" + lblEnd + ")");

            yield return("@" + lblEnd);

            yield return("0;JMP");

            foreach (var st in GenerateEqGtLt(idgen, lblEq, "JEQ"))
            {
                yield return(st);
            }
            foreach (var st in GenerateEqGtLt(idgen, lblGt, "JGT"))
            {
                yield return(st);
            }
            foreach (var st in GenerateEqGtLt(idgen, lblLt, "JLT"))
            {
                yield return(st);
            }
            foreach (var st in GenerateFunCall())
            {
                yield return(st);
            }

            foreach (var st in GenerateReturn())
            {
                yield return(st);
            }
        }
コード例 #3
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessIfGoto(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            yield return("@SP");

            yield return("AM=M-1");

            //yield return "A=M";
            yield return("D=M");

            yield return("@" + stFunc + "$" + vmcmd.StLabel);

            yield return("D;JNE");
        }
コード例 #4
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private IEnumerable <string> ProcessCall(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            var lblNext = idgen.Id("after_call");

            yield return("//r14: hány argumentum van a veremben");

            yield return("//r15: hova kell ugrani");

            yield return("//D: hova kell visszatérni");

            if (vmcmd.I == 0)
            {
                yield return("@R14");

                yield return("M=0");
            }
            else if (vmcmd.I == 1)
            {
                yield return("@R14");

                yield return("M=1");
            }
            else
            {
                yield return("@" + vmcmd.I);

                yield return("D=A");

                yield return("@R14");

                yield return("M=D");
            }

            yield return("@" + idgen.Fun(vmcmd.StFn));

            yield return("D=A");

            yield return("@R15");

            yield return("M=D");

            yield return("@" + lblNext);

            yield return("D=A");

            yield return("@" + lblFunCall);

            yield return("D;JMP");

            yield return("(" + lblNext + ")");
        }
コード例 #5
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> GenerateEqGtLt(Idgen idgen, string lbl, string kjmp)
        {
            yield return("(" + lbl + ")");

            yield return("@R14"); //a = &sp

            yield return("M=D");

            yield return("@SP");   //a = &sp

            yield return("A=M-1"); //a = sp - 1

            yield return("D=M");   //d = sp[1]

            yield return("A=A-1"); //a = sp - 2

            yield return("D=M-D");

            var idTrue  = idgen.Id();
            var idAfter = idgen.Id();

            yield return("@" + idTrue);

            yield return("D;" + kjmp);

            yield return("@" + idAfter);

            yield return("D=0;JEQ");

            yield return("(" + idTrue + ")");

            yield return("D=-1");

            yield return("(" + idAfter + ")");

            yield return("@SP");   //a = &sp

            yield return("M=M-1"); //sp--

            yield return("A=M-1"); //a = sp-1

            yield return("M=D");   //sp[-1] = d

            yield return("@R14");

            yield return("A=M");

            yield return("D;JMP");
        }
コード例 #6
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessNegNot(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            yield return("@SP");   //a = &sp

            yield return("A=M-1"); //a = sp - 1

            if (vmcmd.Kcmd == Kcmd.Neg)
            {
                yield return("M=-M"); //d = -sp[-1]
            }
            else
            {
                yield return("M=!M"); //d = !sp[-1]
            }
        }
コード例 #7
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessFunction(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            yield return("(" + idgen.Fun(vmcmd.StFn) + ")");

            for (int k = 0; k < vmcmd.I; k++)
            {
                yield return("//push 0");

                yield return("@SP");

                yield return("AM=M+1");

                yield return("A=A-1");

                yield return("M=0");
            }
        }
コード例 #8
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        public IEnumerable <string> ToAsm(IEnumerable <string> rgfpat)
        {
            var idgen = new Idgen();

            foreach (var st in Indent(Bootstrap(idgen)))
            {
                yield return(st);
            }


            foreach (var fpat in rgfpat)
            {
                var src = File.ReadAllText(fpat);
                idgen.filn = Path.GetFileName(fpat);
                foreach (var st in Indent(ToAsmI(idgen, src)))
                {
                    yield return(st);
                }
                idgen.filn = null;
            }
        }
コード例 #9
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessAddSubAndOr(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            yield return("@SP");   //a = &sp

            yield return("A=M-1"); //a = sp - 1

            yield return("D=M");   //d = sp[-1]

            yield return("A=A-1"); //a = sp - 2

            switch (vmcmd.Kcmd)
            {
            case Kcmd.Add:
                yield return("M=D+M");    //sp[-2] = sp[-1] + sp[-2]

                break;

            case Kcmd.Sub:
                yield return("M=M-D");    //sp[-2] = sp[-2] - sp[-1]

                break;

            case Kcmd.And:
                yield return("M=D&M");    //sp[-2] = sp[-1] + sp[-2]

                break;

            case Kcmd.Or:
                yield return("M=D|M");    //sp[-2] = sp[-1] + sp[-2]

                break;
            }

            yield return("@SP");   //a = &sp

            yield return("M=M-1"); //sp = sp - 1
        }
コード例 #10
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
 private static IEnumerable <string> ProcessLabel(Vmcmd vmcmd, Idgen idgen, string stFunc)
 {
     yield return("(" + stFunc + "$" + vmcmd.StLabel + ")");
 }
コード例 #11
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessGoto(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            yield return("@" + stFunc + "$" + vmcmd.StLabel);

            yield return("D;JMP");
        }
コード例 #12
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessPush(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            switch (vmcmd.Ksegment)
            {
            case Ksegment.Constant:
            {
                if (vmcmd.I.FIn(0, 1))
                {
                    yield return("@SP");

                    yield return("AM=M+1");

                    yield return("A=A-1");

                    yield return("M={0}".StFormat(vmcmd.I));

                    yield break;
                }
                else
                {
                    yield return("@" + vmcmd.I);

                    yield return("D=A");    //d = vmcmd.I

                    break;
                }
            }

            case Ksegment.Local:
                yield return("@LCL");

                if (vmcmd.I == 0)
                {
                    yield return("A=M");
                }
                else if (vmcmd.I == 1)
                {
                    yield return("A=M+1");
                }
                else
                {
                    yield return("D=M");    //d = vmcmd.I

                    yield return("@" + vmcmd.I);

                    yield return("A=D+A");    //d = vmcmd.I
                }
                yield return("D=M");

                break;

            case Ksegment.Argument:
                yield return("@ARG");

                if (vmcmd.I == 0)
                {
                    yield return("A=M");
                }
                else if (vmcmd.I == 1)
                {
                    yield return("A=M+1");
                }
                else
                {
                    yield return("D=M");    //d = vmcmd.I

                    yield return("@" + vmcmd.I);

                    yield return("A=D+A");    //d = vmcmd.I
                }
                yield return("D=M");

                break;

            case Ksegment.This:
                yield return("@THIS");

                if (vmcmd.I == 0)
                {
                    yield return("A=M");
                }
                else if (vmcmd.I == 1)
                {
                    yield return("A=M+1");
                }
                else
                {
                    yield return("D=M");    //d = vmcmd.I

                    yield return("@" + vmcmd.I);

                    yield return("A=D+A");    //d = vmcmd.I
                }
                yield return("D=M");

                break;

            case Ksegment.That:
                yield return("@THAT");

                if (vmcmd.I == 0)
                {
                    yield return("A=M");
                }
                else if (vmcmd.I == 1)
                {
                    yield return("A=M+1");
                }
                else
                {
                    yield return("D=M");    //d = vmcmd.I

                    yield return("@" + vmcmd.I);

                    yield return("A=D+A");    //d = vmcmd.I
                }

                yield return("D=M");

                break;

            case Ksegment.Temp:
                yield return("@R5");

                if (vmcmd.I == 0)
                {
                    ;
                }
                else if (vmcmd.I == 1)
                {
                    yield return("A=A+1");
                }
                else
                {
                    yield return("D=A");    //d = vmcmd.I

                    yield return("@" + vmcmd.I);

                    yield return("A=D+A");    //d = vmcmd.I
                }
                yield return("D=M");

                break;

            case Ksegment.Pointer:
                yield return("@THIS");

                if (vmcmd.I == 0)
                {
                    ;
                }
                else if (vmcmd.I == 1)
                {
                    yield return("A=A+1");
                }
                else
                {
                    yield return("D=A");    //d = vmcmd.I

                    yield return("@" + vmcmd.I);

                    yield return("A=D+A");    //d = vmcmd.I
                }
                yield return("D=M");

                break;

            case Ksegment.Static:
                yield return("@" + idgen.Static(vmcmd.I));

                yield return("D=M");

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            yield return("@SP");    //a = &sp

            yield return("AM=M+1"); //sp++

            yield return("A=A-1");  //a = sp-1

            yield return("M=D");    //sp[-1] = d
        }
コード例 #13
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private static IEnumerable <string> ProcessPop(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            if (vmcmd.Ksegment == Ksegment.Static)
            {
                yield return("@SP");    //a = &sp

                yield return("AM=M-1"); //sp--

                yield return("D=M");    //d = sp[0]

                yield return("@" + idgen.Static(vmcmd.I));

                yield return("M=D");
            }
            else if (vmcmd.I == 0)
            {
                yield return("@SP");    //a = &sp

                yield return("AM=M-1"); //sp--

                yield return("D=M");    //d = sp[0]

                switch (vmcmd.Ksegment)
                {
                case Ksegment.Local:
                    yield return("@LCL");

                    yield return("A=M");

                    break;

                case Ksegment.Argument:
                    yield return("@ARG");

                    yield return("A=M");

                    break;

                case Ksegment.This:
                    yield return("@THIS");

                    yield return("A=M");

                    break;

                case Ksegment.That:
                    yield return("@THAT");

                    yield return("A=M");

                    break;

                case Ksegment.Temp:
                    yield return("@R5");

                    break;

                case Ksegment.Pointer:
                    yield return("@THIS");

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                yield return("M=D");
            }
            else if (vmcmd.I == 1)
            {
                yield return("@SP");    //a = &sp

                yield return("AM=M-1"); //sp--

                yield return("D=M");    //d = sp[0]

                switch (vmcmd.Ksegment)
                {
                case Ksegment.Local:
                    yield return("@LCL");

                    yield return("A=M+1");

                    break;

                case Ksegment.Argument:
                    yield return("@ARG");

                    yield return("A=M+1");

                    break;

                case Ksegment.This:
                    yield return("@THIS");

                    yield return("A=M+1");

                    break;

                case Ksegment.That:
                    yield return("@THAT");

                    yield return("A=M+1");

                    break;

                case Ksegment.Temp:
                    yield return("@R5");

                    yield return("A=A+1");

                    break;

                case Ksegment.Pointer:
                    yield return("@THIS");

                    yield return("A=A+1");

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
                yield return("M=D");
            }
            else
            {
                switch (vmcmd.Ksegment)
                {
                case Ksegment.Local:
                    yield return("@LCL");

                    yield return("D=M");

                    break;

                case Ksegment.Argument:
                    yield return("@ARG");

                    yield return("D=M");

                    break;

                case Ksegment.This:
                    yield return("@THIS");

                    yield return("D=M");

                    break;

                case Ksegment.That:
                    yield return("@THAT");

                    yield return("D=M");

                    break;

                case Ksegment.Temp:
                    yield return("@R5");

                    yield return("D=A");

                    break;

                case Ksegment.Pointer:
                    yield return("@THIS");

                    yield return("D=A");

                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                yield return("@" + vmcmd.I);

                yield return("D=D+A");

                yield return("@R13");

                yield return("M=D");

                yield return("@SP");    //a = &sp

                yield return("AM=M-1"); //sp--

                yield return("D=M");    //d = sp[0]

                yield return("@R13");

                yield return("A=M");

                yield return("M=D");
            }
        }
コード例 #14
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private IEnumerable <string> ProcessReturn(Vmcmd vmcmd, Idgen idgen, string stFunc)
        {
            yield return("@" + lblReturn);

            yield return("0;JMP");
        }
コード例 #15
0
ファイル: VMTranslator.cs プロジェクト: encse/nand2tetris
        private IEnumerable <string> ToAsmI(Idgen idgen, string src)
        {
            string stFunc = null;

            foreach (var vmcmd in EnvmcdParse(src))
            {
                yield return("//" + vmcmd.Unparse());

                Func <Vmcmd, Idgen, string, IEnumerable <string> > dg;
                switch (vmcmd.Kcmd)
                {
                case Kcmd.Label: dg = ProcessLabel; break;

                case Kcmd.Goto: dg = ProcessGoto; break;

                case Kcmd.IfGoto: dg = ProcessIfGoto; break;

                case Kcmd.Add:
                case Kcmd.Sub:
                case Kcmd.And:
                case Kcmd.Or:
                    dg = ProcessAddSubAndOr;
                    break;

                case Kcmd.Neg:
                case Kcmd.Not:
                    dg = ProcessNegNot;
                    break;

                case Kcmd.Eq:
                case Kcmd.Gt:
                case Kcmd.Lt:
                    dg = ProcessEqGtLt;
                    break;

                case Kcmd.Push:
                    dg = ProcessPush;
                    break;

                case Kcmd.Pop:
                    dg = ProcessPop;
                    break;

                case Kcmd.Call:
                    dg = ProcessCall;
                    break;

                case Kcmd.Function:
                    stFunc = vmcmd.StFn;
                    dg     = ProcessFunction;
                    break;

                case Kcmd.Return:
                    dg = ProcessReturn;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                foreach (var st in dg(vmcmd, idgen, stFunc))
                {
                    yield return(st);
                }
            }
        }