[Home]P-code machine

HomePage | Recent Changes | Preferences

A virtual machine executing P-code, the P-code machine or P-System was the target of early Pascal compilers. That is, the programming language Pascal was translated not to machine code understandable directly to a processor, but to P-code. To execute the program, another program is used that interprets this code.

The P-code machine is stack-oriented, which means that most instructions take their operands from the stack, and place results back on the stack. So adding replaces the two topmost elements of the stack with their sum. A few instructions take an immediate argument. Like Pascal, p-code is strongly typed, supporting boolean (b), character (c), integer (i), real (r), set (s), and pointer (a) types natively.

Some simple instructions:

 Insn.   Stack   Stack   Description
         before  after

 adi      i1 i2   i1+i2   add two integers
 adr      r1 r2   r1+r2   add two reals
 dvi      i1 i2   i1/i2   integer division
 inn      i1 s1   b1      set membership; b1 = whether i1 is a member of s1
 ldci i1          i1      load integer constant
 mov      a1 a2           move
 not      b1      ~b1     boolean negation


Differing from other stack-based environments (Forth, the Java virtual machine) the P-system has only one stack shared by procedure stack frames (providing return address, etc.) and the arguments to local instructions. Three of the machine's registers point into the stack (which grows upwards):

Also present is a constant area, and, below that, the heap growing down towards the stack. The NP register points to the top (lowest used address) of the heap. When EP gets greater than NP, the machine's memory is exhausted.

The fifth register, PC, points at the current instruction in the code area.

Calling Conventions

Stack frames look like this:

 EP ->
       local stack
 SP -> ...
       return address (previous PC)
       previous EP
       dynamic link (previous MP)
       static link (MP of surrounding procedure)
 MP -> function return value

The procedure calling sequence works as follows: The call is introduced with

  mst n
where n specifies the difference in nesting levels (remember that Pascal supports nested procedures). This instruction will mark the stack, i.e. reserve the first five cells of the above stack frame, and initialise previous EP, dynamic, and static link. The caller then computes and pushes any parameters for the procedure, and then issues
  cup n, p
to call a user procedure (n being the number of parameters, p the procedure's address). This will save the PC in the return address cell, and set the procedure's address as the new PC.

User procedures begin with the two instructions

  ent 1, i
  ent 2, j
The first sets SP to MP + i, the second sets EP to SP + j. So i essentially specifies the space reserved for locals (plus the number of parameters plus 5), and j gives the number of entries needed locally for the stack. Memory exhaustion is checked at this point.

Returning to the caller is accomplished via

with C giving the return type (i, r, c, b, a as above, and p for no return value). The return value has to be stored in the appropriate cell previously. On all types except p, returning will leave this value on the stack.

Instead of calling a user procedure (cup), standard procedure q can be called with

  csp q
These standard procedures are Pascal procedures like readln() ("csp rln"), sin() ("csp sin"), etc. Peculiarly eof() is a P-code instruction instead.

Further Reading

HomePage | Recent Changes | Preferences
This page is read-only | View other revisions
Last edited November 25, 2001 10:54 pm by Robbe (diff)