示例#1
0
        public static void Emulator(int initPC, int codeLen, int initSP,
                                InFile data, OutFile results, bool tracing)
        {
            // Emulates action of the codeLen instructions stored in mem[0 .. codeLen-1], with
            // program counter initialized to initPC, stack pointer initialized to initSP.
            // data and results are used for I/O.  Tracing at the code level may be requested

              int pcNow;                  // current program counter
              int loop;                   // internal loops
              int tos, sos;               // value popped from stack
              int adr;                    // effective address for memory accesses
              stackBase = initSP;
              heapBase = codeLen;         // initialize boundaries
              cpu.hp = heapBase;          // initialize registers
              cpu.sp = stackBase;
              cpu.gp = stackBase;
              cpu.mp = stackBase;
              cpu.fp = stackBase;
              cpu.pc = initPC;            // initialize program counter
              ps = running;               // prepare to execute
              int ops = 0;
              timer.Start();
              do {
            ops++;
            pcNow = cpu.pc;           // retain for tracing/postmortem
            if (cpu.pc < 0 || cpu.pc >= codeLen) {
              ps = badAdr;
              break;
            }
            cpu.ir = Next();          // fetch
            if (tracing) Trace(results, pcNow);
            switch (cpu.ir) {         // execute
              case PVM.nop:           // no operation
            break;
              case PVM.dsp:           // decrement stack pointer (allocate space for variables)
            int localSpace = Next();
            cpu.sp -= localSpace;
            if (InBounds(cpu.sp)) // initialize
              for (loop = 0; loop < localSpace; loop++)
                mem[cpu.sp + loop] = 0;
            break;
              case PVM.ldc:           // push constant value
            Push(Next());
            break;
              case PVM.lda:           // push local address
            adr = cpu.fp - 1 - Next();
            if (InBounds(adr)) Push(adr);
            break;
              case PVM.ldv:           // dereference
            Push(mem[Pop()]);
            break;
              case PVM.sto:           // store
            tos = Pop(); adr = Pop();
            if (InBounds(adr)) mem[adr] = tos;
            break;
              case PVM.ldxa:          // heap array indexing
            adr = Pop();
            int heapPtr = Pop();
            if (heapPtr == 0) ps = nullRef;
            else if (heapPtr < heapBase || heapPtr >= cpu.hp) ps = badMem;
            else if (adr < 0 || adr >= mem[heapPtr]) ps = badInd;
            else Push(heapPtr + adr + 1);
            break;
              case PVM.inpi:          // integer input
            adr = Pop();
            if (InBounds(adr)) {
              mem[adr] = data.ReadInt();
              if (data.Error()) ps = badData;
            }
            break;
              case PVM.prni:          // integer output
            if (tracing) results.Write(padding);
            results.Write(Pop(), 0);
            if (tracing) results.WriteLine();
            break;
              case PVM.inpb:          // boolean input
            adr = Pop();
            if (InBounds(adr)) {
              mem[adr] = data.ReadBool() ? 1 : 0;
              if (data.Error()) ps = badData;
            }
            break;
              case PVM.prnb:          // boolean output
            if (tracing) results.Write(padding);
            if (Pop() != 0) results.Write(" true  "); else results.Write(" false ");
            if (tracing) results.WriteLine();
            break;
              case PVM.prns:          // string output
            if (tracing) results.Write(padding);
            loop = Next();
            while (ps == running && mem[loop] != 0) {
              results.Write((char) mem[loop]); loop--;
              if (loop < stackBase) ps = badMem;
            }
            if (tracing) results.WriteLine();
            break;
              case PVM.prnl:          // newline
            results.WriteLine();
            break;
              case PVM.neg:           // integer negation
            Push(-Pop());
            break;
              case PVM.add:           // integer addition
            tos = Pop(); Push(Pop() + tos);
            break;
              case PVM.sub:           // integer subtraction
            tos = Pop(); Push(Pop() - tos);
            break;
              case PVM.mul:           // integer multiplication
            tos = Pop(); Push(Pop() * tos);
            break;
              case PVM.div:           // integer division (quotient)
            tos = Pop(); Push(Pop() / tos);
            break;
              case PVM.rem:           // integer division (remainder)
            tos = Pop(); Push(Pop() % tos);
            break;
              case PVM.not:           // logical negation
            Push(Pop() == 0 ? 1 : 0);
            break;
              case PVM.and:           // logical and
            tos = Pop(); Push(Pop() & tos);
            break;
              case PVM.or:            // logical or
            tos = Pop(); Push(Pop() | tos);
            break;
              case PVM.ceq:           // logical equality
            tos = Pop(); Push(Pop() == tos ? 1 : 0);
            break;
              case PVM.cne:           // logical inequality
            tos = Pop(); Push(Pop() != tos ? 1 : 0);
            break;
              case PVM.clt:           // logical less
            tos = Pop(); Push(Pop() <  tos ? 1 : 0);
            break;
              case PVM.cle:           // logical less or equal
            tos = Pop(); Push(Pop() <= tos ? 1 : 0);
            break;
              case PVM.cgt:           // logical greater
            tos = Pop(); Push(Pop() >  tos ? 1 : 0);
            break;
              case PVM.cge:           // logical greater or equal
            tos = Pop(); Push(Pop() >= tos ? 1 : 0);
            break;
              case PVM.brn:           // unconditional branch
            cpu.pc = Next();
            if (cpu.pc < 0 || cpu.pc >= codeLen) ps = badAdr;
            break;
              case PVM.bze:           // pop top of stack, branch if false
            int target = Next();
            if (Pop() == 0) {
              cpu.pc = target;
              if (cpu.pc < 0 || cpu.pc >= codeLen) ps = badAdr;
            }
            break;
              case PVM.anew:          // heap array allocation
            int size = Pop();
            if (size <= 0 || size + 1 > cpu.sp - cpu.hp - 2)
              ps = badAll;
            else {
              mem[cpu.hp] = size;
              Push(cpu.hp);
              cpu.hp += size + 1;
            }
            break;
              case PVM.halt:          // halt
            ps = finished;
            break;
              case PVM.stk:           // stack dump (debugging)
            StackDump(results, pcNow);
            break;
              case PVM.heap:           // heap dump (debugging)
            HeapDump(results, pcNow);
            break;
              case PVM.ldc_0:         // push constant 0
              case PVM.ldc_1:         // push constant 1
              case PVM.ldc_2:         // push constant 2
              case PVM.ldc_3:         // push constant 3
              case PVM.lda_0:         // push local address 0
              case PVM.lda_1:         // push local address 1
              case PVM.lda_2:         // push local address 2
              case PVM.lda_3:         // push local address 3
              case PVM.ldl:           // push local value
              case PVM.ldl_0:         // push value of local variable 0
              case PVM.ldl_1:         // push value of local variable 1
              case PVM.ldl_2:         // push value of local variable 2
              case PVM.ldl_3:         // push value of local variable 3
              case PVM.stl:           // store local value
              case PVM.stlc:          // store local value
              case PVM.stl_0:         // pop to local variable 0
              case PVM.stl_1:         // pop to local variable 1
              case PVM.stl_2:         // pop to local variable 2
              case PVM.stl_3:         // pop to local variable 3
              case PVM.stoc:          // character checked store
              case PVM.inpc:          // character input
              case PVM.prnc:          // character output
              case PVM.low:           // toLowerCase
              case PVM.islet:         // isLetter
              case PVM.inc:           // ++
              case PVM.dec:           // --
              default:              // unrecognized opcode
            ps = badOp;
            break;
            }
              } while (ps == running);
              TimeSpan ts = timer.Elapsed;

              // Format and display the TimeSpan value.
              string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
              ts.Hours, ts.Minutes, ts.Seconds,
              ts.Milliseconds / 10);
              Console.WriteLine("\n\n" + ops + " operations.  Run Time " + elapsedTime + "\n\n");
              if (ps != finished) PostMortem(results, pcNow);
              timer.Reset();
              timer.Stop();
        }
示例#2
0
        // The interpreters and utility methods
        public static void Emulator(int initPC, int codeLen, int initSP,
                                InFile data, OutFile results, bool tracing)
        {
            // Emulates action of the codeLen instructions stored in mem[0 .. codeLen-1], with
            // program counter initialized to initPC, stack pointer initialized to initSP.
            // data and results are used for I/O.  Tracing at the code level may be requested

              int pcNow;                  // current program counter
              int loop;                   // internal loops
              int tos, sos;               // value popped from stack
              stackBase = initSP;
              heapBase = codeLen;         // initialize boundaries
              cpu.hp = heapBase;          // initialize registers
              cpu.sp = stackBase;
              cpu.gp = stackBase;
              cpu.mp = stackBase;
              cpu.fp = stackBase;
              cpu.pc = initPC;            // initialize program counter
              ps = running;               // prepare to execute
              int ops = 0;
              timer.Start();
              do {
            ops++;
            pcNow = cpu.pc;           // retain for tracing/postmortem
            cpu.ir = mem[cpu.pc++];          // fetch
            //        if (tracing) Trace(results, pcNow);
            switch (cpu.ir) {         // execute
              case PVM.nop:           // no operation
            break;
              case PVM.dsp:           // decrement stack pointer (allocate space for variables)
            cpu.sp -= mem[cpu.pc++];
            break;
              case PVM.ldc:           // push constant value
            mem[--cpu.sp] = mem[cpu.pc++];
            break;
              case PVM.lda:           // push local address
            mem[--cpu.sp] = cpu.fp - 1 - mem[cpu.pc++];
            break;
              case PVM.ldv:           // dereference
            mem[cpu.sp] = mem[mem[cpu.sp]];
            break;
              case PVM.sto:           // store
            tos = mem[cpu.sp++]; mem[mem[cpu.sp++]] = tos;
            break;
              case PVM.ldxa:          // heap array indexing
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] + tos;
            break;
              case PVM.inpi:          // integer input
            mem[mem[cpu.sp++]] = data.ReadInt();
            break;
              case PVM.prni:          // integer output
            //            if (tracing) results.Write(padding);
            results.Write(mem[cpu.sp++], 0);
            //            if (tracing) results.WriteLine();
            break;
              case PVM.inpb:          // boolean input
            mem[mem[cpu.sp++]] = data.ReadBool() ? 1 : 0;
            break;
              case PVM.prnb:          // boolean output
            //            if (tracing) results.Write(padding);
            if (mem[cpu.sp++] != 0) results.Write(" true  "); else results.Write(" false ");
            //            if (tracing) results.WriteLine();
            break;
              case PVM.prns:          // string output
            //            if (tracing) results.Write(padding);
            loop = mem[cpu.pc++];
            while (mem[loop] != 0) {
              results.Write((char) mem[loop]); loop--;
            }
            //            if (tracing) results.WriteLine();
            break;
              case PVM.prnl:          // newline
            results.WriteLine();
            break;
              case PVM.neg:           // integer negation
            mem[cpu.sp] = -mem[cpu.sp];
            break;
              case PVM.add:           // integer addition
            tos = mem[cpu.sp++]; mem[cpu.sp] += tos;
            break;
              case PVM.sub:           // integer subtraction
            tos = mem[cpu.sp++]; mem[cpu.sp] -= tos;
            break;
              case PVM.mul:           // integer multiplication
            tos = mem[cpu.sp++]; mem[cpu.sp] *= tos;
            break;
              case PVM.div:           // integer division (quotient)
            tos = mem[cpu.sp++]; mem[cpu.sp] /= tos;
            break;
              case PVM.rem:           // integer division (remainder)
            tos = mem[cpu.sp++]; mem[cpu.sp] %= tos;
            break;
              case PVM.not:           // logical negation
            mem[cpu.sp] = mem[cpu.sp] == 0 ? 1 : 0;
            break;
              case PVM.and:           // logical and
            tos = mem[cpu.sp++]; mem[cpu.sp] &= tos;
            break;
              case PVM.or:            // logical or
            tos = mem[cpu.sp++]; mem[cpu.sp] |= tos;
            break;
              case PVM.ceq:           // logical equality
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] == tos ? 1 : 0;
            break;
              case PVM.cne:           // logical inequality
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] != tos ? 1 : 0;
            break;
              case PVM.clt:           // logical less
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] <  tos ? 1 : 0;
            break;
              case PVM.cle:           // logical less or equal
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] <= tos ? 1 : 0;
            break;
              case PVM.cgt:           // logical greater
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] >  tos ? 1 : 0;
            break;
              case PVM.cge:           // logical greater or equal
            tos = mem[cpu.sp++]; mem[cpu.sp] = mem[cpu.sp] >= tos ? 1 : 0;
            break;
              case PVM.brn:           // unconditional branch
            cpu.pc = mem[cpu.pc++];
            break;
              case PVM.bze:           // pop top of stack, branch if false
            int target = mem[cpu.pc++];
            if (mem[cpu.sp++] == 0) cpu.pc = target;
            break;
              case PVM.anew:          // heap array allocation
            int size = mem[cpu.sp];
            mem[cpu.sp] = cpu.hp;
            cpu.hp += size;
            break;
              case PVM.halt:          // halt
            ps = finished;
            break;
              case PVM.stk:           // stack dump (debugging)
            StackDump(results, pcNow);
            break;
              case PVM.heap:           // heap dump (debugging)
            HeapDump(results, pcNow);
            break;
              case PVM.ldc_0:         // push constant 0
              case PVM.ldc_1:         // push constant 1
              case PVM.ldc_2:         // push constant 2
              case PVM.ldc_3:         // push constant 3
              case PVM.lda_0:         // push local address 0
              case PVM.lda_1:         // push local address 1
              case PVM.lda_2:         // push local address 2
              case PVM.lda_3:         // push local address 3
              case PVM.ldl:           // push local value
              case PVM.ldl_0:         // push value of local variable 0
              case PVM.ldl_1:         // push value of local variable 1
              case PVM.ldl_2:         // push value of local variable 2
              case PVM.ldl_3:         // push value of local variable 3
              case PVM.stl:           // store local value
              case PVM.stlc:          // store local value
              case PVM.stl_0:         // pop to local variable 0
              case PVM.stl_1:         // pop to local variable 1
              case PVM.stl_2:         // pop to local variable 2
              case PVM.stl_3:         // pop to local variable 3
              case PVM.stoc:          // character checked store
              case PVM.inpc:          // character input
              case PVM.prnc:          // character output
              case PVM.low:           // toLowerCase
              case PVM.islet:         // isLetter
              case PVM.inc:           // ++
              case PVM.dec:           // --
              default:                // unrecognized opcode
            ps = badOp;
            break;
            }
              } while (ps == running);
              TimeSpan ts = timer.Elapsed;

              // Format and display the TimeSpan value.
              string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
              ts.Hours, ts.Minutes, ts.Seconds,
              ts.Milliseconds / 10);
              Console.WriteLine("\n\n" + ops + " operations.  Run Time " + elapsedTime + "\n\n");
              if (ps != finished) PostMortem(results, pcNow);
              timer.Reset();
              timer.Stop();
        }