No love for the address?

I’ve been looking more into the & operator, which seems pretty great. But it doesn’t seem to be fully supported.

When reading through the code that decode parameters, and looking at the comments, the code seems to fully decode the address, but the comment have completely emitted the information.

So basically, the compiler builds a stream of bytes form the LMS code. The byte stream is super simple. It is a byte that represent the opcode, and then a bunch of bytes representing potential parameters. If we look at the byte code for:

MOVE32_32( 1145324612, MyVar1 )

It can compile into:

3A834444444440

If we split it up into opcode and parameters it becomes this:

0x3a,         // Opcode for MOVE32_32
0x83,         // Information for first parameter.  Binary: 1000 0011
0x44444444,   // Constant for 1145324612
0x40,         // Information for second parameter. Binary: 0100 0000

So the opcode is 0x3a, and if we look at the native code for MOVE32_32 we see this:

void      cMove32to32(void)
{
  DATA32  Tmp;

  Tmp  =  *(DATA32*)PrimParPointer();
  *(DATA32*)PrimParPointer()  =  Tmp;
}

That code contain two calls to PrimParPointer, and what that does is first look at the information for the parameter, and then either fetch a constant, fetch a local or global variable. The bitfield is explained as a comment for PrimParPointer and looks like this:

/*! \page parameterencoding Parameter Encoding
 *
 *  Parameter types and values for primitives, system calls and subroutine calls are encoded in the callers byte code stream as follows:
 *
 *  opADD8 (ParCode1, ParCode2, ParCodeN)
 * \verbatim
Bits  76543210
      --------
      0Ttxxxxx    short format
      ||||||||
      |0||||||    constant
      ||||||||
      ||0vvvvv    positive value
      ||1vvvvv    negative value
      |||
      |1|         variable
      | |
      | 0iiiii    local index
      | 1iiiii    global index
      |
      1ttt-bbb    long format
       ||| |||
       0|| |||    constant
       ||| |||
       |0| |||    value
       |1| |||    label
       ||| |||
       1|| |||    variable
        || |||
        0| |||    local
        1| |||    global
         | |||
         0 |||    value
         1 |||    handle
           |||
           000    Zero terminated string  (subject to change)
           001    1 bytes to follow       (subject to change)
           010    2 bytes to follow       (subject to change)
           011    4 bytes to follow       (subject to change)
           100    Zero terminated string  \endverbatim
 *
 */

So if we again look at our parameters. First the first parameter:

Binary: 1000 0011

According to the comment it is in long format, it is a constant, it is a value and it contains four bytes. The PrimParPointer will the go on to read those 4 bytes from the byte stream, which are as we saw earlier

0x44444444

The second parameter information is then:

Binary: 0100 0000

So according to the comment that means it is in short format, it is a variable, and the variable index is 0.

So that’s it, that is how the parameter encoding works. Those of you with a keen eye may have noticed that in the long format there is one bit that isn’t explained. Bit 3. (If you follow their naming of the bits) Bit 4 explain if it is a handle or not, but bit 3 is left out.

So I went back to look at the code that is generated for this:

MOVE32_32( &MyVar1, MyVar2 )

And the generated byte code is:

0x3A,  // Opcode for MOVE32_32
0xC9,  // First parameter information.  Binary: 1100 1001
0x00,  // ??
0x44,  // Second parameter information. Binary: 0100 0100

The encoding of the parameter information when doing & seems to be perfectly fine, and the code in PrimParPointer seems to be perfectly valid too. It looks like this:

    if (Data & PRIMPAR_HANDLE)
    {
      VMInstance.Handle  =  *(HANDLER*)Result;
      cMemoryArraryPointer(VMInstance.ProgramId,VMInstance.Handle,&Result);
    }
    else
    {
      if (Data & PRIMPAR_ADDR)
      {
        Result  =  (void*)*(DATA32*)Result;
        VMInstance.Value  =  (DATA32)Result;
      }
    }

So it seems like the @ operator (handle) will return the pointer to an address based on a handle used when calling ARRAY( CREATEx, … ) and the & operator (address) will type case the Result (which is a pointer) and dereference that address to get a new address, which it returns.

I’m confused..

In any case, that 0x00 that snuck in straight after the 0xc9 seems misplaced, but other than that it seems like addresses may work. I will remove the 0x00 and see what the VM think about that.

Leave a Reply