Web 51 P-Code Interpreter

RTL8019AS Packet Driver 4  software.html  P-Code, arith, branch

Part 1 - P-Code Structure and Interpreter

Portions of Web 51 utilize the P-Code Interpreter to achieve two goals:

P-Code structure responds to several requirements:

Taking into account the above requirements, the following structure can be used:

AAAAAAAA  procedure address MSB
AAAAAAAA       -"-          LSB
__SSSIII  options: (S)wap LSB/MSB, (I)ndirect address
11111111  parameter 1 MSB (MSB1)
11111111     -"-      LSB (LSB1)
22222222  parameter 2 MSB (MSB2)
22222222     -"-      LSB (LSB2)
33333333  parameter 3 MSB (MSB3)
33333333     -"-      LSB (LSB3)

Such a code would use 9 bytes per instruction. That is quite a lot, considering that many commands won't use all three parameters. More, parameters are often only 8 bits wide. Solution is simple. The P-Code structure will contain 6 additional bits, specifying whether any of the corresponding parameter bytes (MSB1 to LSB3) are equal to zero. Additional bits allow variable P-Code length - now it is possible to omit entire parameters or their MSB/LSB parts if equal to zero. Placing a little limitation on MSB/LSB swapping of the second parameter and shortening procedure address to 13 bits, the following structure is obtained:

IIIAAAAA  procedure address MSB, (I)ndirect parameter address
AAAAAAAA       -"-          LSB
abcdefSS  option: (S)wap LSB/MSB, parameter MSB1..LSB3 non-zero
11111111  parametr 1 MSB (MSB1 - a)
11111111     -"-     LSB (LSB1 - b)
22222222  parametr 2 MSB (MSB2 - c)
22222222     -"-     LSB (LSB2 - d)
33333333  parametr 3 MSB (MSB3 - e)
33333333     -"-     LSB (LSB3 - f)

Resulting P-Code instruction is 3 to 9 bytes long. The following macro (from an old versions of our development system) shows its construction:

; pcode EQU
blank equ 0
none  EQU 0000h
IND1  EQU 8000h ;par1 INDirect
IND2  EQU 4000h ;par2 INDirect
IND3  EQU 2000h ;par3 INDirect
SWAP1 EQU 8002h ;always Indirect & Swap
SWAP3 EQU 2001h
DP    MACRO fce, option, par1, par2, par3
      DW fce + (option and 0E000h)
btk1  SET 0
btk2  SET 0
btk3  SET 0
btk4  SET 0
btk5  SET 0
btk6  SET 0
if (par1 SHR 8) <> 0    btk1 SET 10000000b endif
if (par1 AND 0FFh) <> 0 btk2 SET 01000000b endif
if (par2 SHR 8) <> 0    btk3 SET 00100000b endif
if (par2 AND 0FFh) <> 0 btk4 SET 00010000b endif
if (par3 SHR 8) <> 0    btk5 SET 00001000b endif
if (par3 AND 0FFh) <> 0 btk6 SET 00000100b endif
      DB btk1 or btk2 or btk3 or btk4 or btk5 or btk6 or (option and 0003h)
if (par1 SHR 8) <> 0
      DB high(par1)
if (par1 AND 0FFh) <> 0
      DB low(par1)
if (par2 SHR 8) <> 0
      DB high(par2)
if (par2 AND 0FFh) <> 0
      DB low(par2)
if (par3 SHR 8) <> 0
      DB high(par3)
if (par3 AND 0FFh) <> 0
      DB low(par3)

Parameter definitions at the beginning indicate that SWAP flags are only effective together with corresponding INDirect flags (it is possible to swap LSB/MSB of a literal value at compile-time). Procedure address definition says that 13 bits are available. This is not entirely true. A termination character, binary zero, is used to indicate that a P-Code section ends and machine code continues (similarly to ASCIIZ text strings). A P-Code sequence is terminated by, for example, .byte 0 (or DB 0 for Intel/Keil assemblers). However, this zero byte must not be taken as the address field of another P-Code instruction without INDirect parameters. Therefore, MSB of the address may not be zero. This further restricts the address range of P-Code execution procedures to 100h...1FFFh, and must be taken into account when linking. No P-Procedure may begin within 0000...00FFh.

Parameters are passed by the P-Code interpreter to the P-Procedures in registers:

If the P-Code instruction has less than 6 bytes of parameters, omitted values are zeroed out. First, parameters are read into the registers. Then, any INDirect parameters are processed. If the flag is set, LSB part of the corresponding register pair (that is, register R7, R5 or R3) is taken as an address into the internal RAM and a 16-bit value is fetched in MSB-LSB order, as shown in the following code fragment:

NoOpt2: JNB token.7,noI1
        MOV A,R7
        MOV R0,A
        MOV A,@R0
        MOV R6,A
        INC R0
        MOV A,@R0
        MOV R7,A
noI1:   JNB token.6,noI2

Then, Swap flags are evaluated, swapping LSB and MSB parts of corresponding register pairs if set. Again, a code fragment is the best explanation:

noI3:   jnb pcodeOption.1,NoOpt1
        MOV A,R6   ;swap1
        XCH A,R7
        MOV R6,A
NoOpt1: jnb pcodeOption.0,NoOpt0

The DP macro (above) is universal. It automatically detects sizes (and presence) of parameters. However, since a program can be split into modules, it is necessary to have the option of specifying sizes (BYTE/WORD) of parameters explicitly. Macros DPB__, ..., DP__B, ..., DPW__, where B, W or _ at the appropriate position indicates byte-, word- or auto-sized parameter, serve for this purpose.

Current version of the development system uses native support of mcs51-as (assembler).

Syntax of the .pcode command is similar to that of standard MCS51 instruction set. Three main addressing modes are used:

What are the differences?

Direct constant and variable are the same - both pass the given value into the P-Procedure. Different syntax for a constant and a variable only serves to make source code more legible. Whether the parameter is a constant or an address of a variable depends only on the P-Procedure being called.

Indirect constant sets the P-Code Indirect flag. P-Code Interpreter fetches the value from the specified address before calling the P-Procedure, as shown above.

Several other modifiers effect parameters passing:

Part 2P-Code Interpreter, part 2

Sponzored by LPhard Ltd. Graphics by GIMP Created by EasyPad

(c)Copyright 2000 - 2002, HW server & Radek Benedikt
Web51@HW.cz, Web51.HW.cz
RTL8019AS Packet Driver 4  Obsah  P-Code, arith, branch