David BoddieAdded some more notes.9e7fadd9 years agoHistory
177 lines · 4.9 KB · Text
RawDownload
Opcode definitions------------------ Opcodes are defined in include/isa.h, limbo/optab.c and libinterp/xec.c. consc is documented but does not exist in the opcode definitions. Function signatures------------------- Function signatures will be output by the Limbo compiler if you pass it the"-D S" debug option. For example, the Sys->print function has this summary output for it:     signed Sys->print type fn(s: string, *): int len 6 sig 0xac849033 The type "fn(s: string, *): int" is how the function is declared in themodule/sys.m file. Function signatures are generated by the sign function in the limbo/types.cfile. We add the debug code after the md5 function call:     md5(sig, sigend, md5sig, nil);    if(debug['S']) {        print("sign %D len %d\n", d, sigend);        print("%s\n", (char*)sig);    } This results in the following additional two debug lines:     sign Sys->print len 6    f*(s)i The "f*(s)i" string is the function signature that needs to be hashed using theMD5 algorithm. Additionally, the following code is used to reduce the hashvalue to four bytes:     for(i = 0; i < MD5dlen; i += 4)        t->sig ^= md5sig[i+0] | (md5sig[i+1]<<8) | (md5sig[i+2]<<16) | (md5sig[i+3]<<24); We can reproduce this in Python using the md5 module, obtaining the hash valuethen combining each eight digit segment of it using XOR, before reversing theendianness of the resulting value:     import md5    h = md5.md5("f*(s)i").hexdigest()    l = map(lambda x: int(h[x:x+2], 16), range(0, 32, 2))    hd = sum(map(lambda x: reduce(lambda y, z: y ^ z, l[x::4]) << (x * 8), range(4))) The rtsign and idsign functions in the limbo/types.c file are responsible forcreating a signature for a function. The sigkind array contains the charactersused for each type of object that will be serialised. Operands-------- The double indirect operands SO(SO(fp)) and SO(SO(mp)) are represented by twooffsets in the encoded instruction. The first represents the "inner" offset,the second the "outer" offset. For example:     10(20(fp)) is represented as 20, 10 in the instruction. This was discovered by running the Limbo compiler with the -S option. Register allocation and stack frames------------------------------------ The following program was compiled using the Limbo compiler:     implement count;     include "sys.m";    include "draw.m";     count: module    {        init: fn(ctxt: ref Draw->Context, args: list of string);    };     init(ctxt: ref Draw->Context, args: list of string)    {        sys := load Sys Sys->PATH;        sys->print("Counting...\n");        for (i := 0; i < 20; i++)            sys->print("%d\n", i);    } It was disassembled to produce this listing:     0x0: load 0(mp), $0x0, 44(fp)    0x1: frame $0x1, 52(fp)    0x2: movp 8(mp), 32(52(fp))    0x3: lea 48(fp), 16(52(fp))    0x4: mcall 52(fp), $0x0, 44(fp)    0x5: movw $0x0, 40(fp)    0x6: blew $0x7b, 40(fp), $0xe    0x7: frame $0x1, 48(fp)    0x8: movp 4(mp), 32(48(fp))    0x9: movw 40(fp), 36(48(fp))    0xa: lea 52(fp), 16(48(fp))    0xb: mcall 48(fp), $0x0, 44(fp)    0xc: addw $0x1, 40(fp)    0xd: jmp $0x6    0xe: ret     entry 0x0, 2    desc $0x0, 16, "f0"    desc $0x1, 40, "0080"    desc $0x2, 56, "00d0"     var @mp, 16    string @mp+0, "$Sys"    string @mp+4, "%d\n"    string @mp+8, "Counting...\n"     module count     link 0x0, 2, 0x4244b354, "init"     ldts @ldt, 1    word @ldt+0,1    ext @ldt+4, 0xac849033, "print"     source "/usr/david/count.b" The entry line gives the initial PC value and the type (2) containing stackframe information:     desc $0x2, 56, "00d0" This type contains 56 bytes and the pointer bitmap indicates that offsets 32,36 and 44 are pointers:     0   4   8  12  16  20  24  28 | 32  36  40  44  48  52  56  60                                     *   *       *    0   0   0   0   0   0   0   0    1   1   0   1   0   0   0   0  0x00d0 The code starts at pc=0x0 where it loads a module:     0x0: load 0(mp), $0x0, 44(fp)   ; path, linkage descriptor, destination In this instruction, the path refers to this item in the data section:     string @mp+0, "$Sys" The linkage descriptor refers to the first sequence of items in the ldts area(there is only one):     word @ldt+0,1    ext @ldt+4, 0xac849033, "print" The result is placed in the pointer at 44(fp) which represents the sysvariable. A stack frame is created so that a function can be called:     0x1: frame $0x1, 52(fp)     ; type index, destination This specifies the type (1) containing stack frame information:     desc $0x1, 40, "0080" In this frame, only offset 32 is a pointer. The result of the frame instructionis held in 52(fp) which should be a pointer, but apparently isn't recorded asone. The next instruction copies the location of a string into the new frame at anaddress in the frame that is marked as a pointer:     0x2: movp 8(mp), 32(52(fp))     ; source, destination     string @mp+8, "Counting...\n"       0x3: lea 48(fp), 16(52(fp))