Ticket #1105: libjit.patch

File libjit.patch, 107.8 KB (added by plobsing, 12 years ago)
  • src/frame_builder.c

     
    77/* HEADERIZER STOP */ 
    88 
    99#include "parrot/parrot.h" 
    10 #include "pmc/pmc_fixedintegerarray.h" 
    11 #include "pmc/pmc_unmanagedstruct.h" 
    12 #include "pmc/pmc_managedstruct.h" 
    1310#include "frame_builder.h" 
    1411 
    15 /* 
    16  
    17 =over 4 
    18  
    19 =item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)> 
    20  
    21 This is a callback to implement the proper freeing semantics.  It is called by 
    22 the ManagedStruct PMC as it is garbage collected. 
    23  
    24 =cut 
    25  
    26 */ 
    27  
    28 void 
    29 Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv) 
    30 { 
    31     const struct jit_buffer_private_data * const jit = (struct jit_buffer_private_data*)priv; 
    32     mem_free_executable(ptr, jit->size); 
    33     free(priv); 
    34 } 
    35  
    36 /* 
    37  
    38 =item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)> 
    39  
    40 This is a callback to implement the proper cloning semantics for jit buffers. 
    41 It is called by the ManagedStruct PMC's clone() function. 
    42  
    43 =back 
    44  
    45 =cut 
    46  
    47 */ 
    48  
    49 PMC * 
    50 Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv) 
    51 { 
    52     PMC * const rv = pmc_new(interp, pmc->vtable->base_type); 
    53  
    54     VTABLE_init(interp, rv); 
    55     /* copy the attributes */ 
    56     { 
    57         void (*tmpfreefunc)(PARROT_INTERP, void*, void*); 
    58         GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc); 
    59         SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc); 
    60     } 
    61     { 
    62         PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*); 
    63         GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc); 
    64         SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc); 
    65     } 
    66  
    67     { 
    68         void *freepriv, *clonepriv; 
    69         GETATTR_ManagedStruct_custom_free_priv(interp , pmc, freepriv); 
    70         GETATTR_ManagedStruct_custom_clone_priv(interp, pmc, clonepriv); 
    71         if (freepriv) { 
    72             void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); 
    73             memcpy(tmp, freepriv, sizeof (struct jit_buffer_private_data)); 
    74             SETATTR_ManagedStruct_custom_free_priv(interp, rv , tmp); 
    75             if (clonepriv == freepriv) { 
    76                 /* clonepriv is a copy of freepriv, make it a copy in the clone too. */ 
    77                 SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp); 
    78                 clonepriv = NULL; /* disable the clonepriv copying below */ 
    79             } 
    80         } 
    81         if (clonepriv) { 
    82             void *tmp = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); 
    83             memcpy(tmp, clonepriv, sizeof (struct jit_buffer_private_data)); 
    84             SETATTR_ManagedStruct_custom_clone_priv(interp, rv , tmp); 
    85         } 
    86     } 
    87  
    88     /* copy the execmem buffer */ 
    89     if (PARROT_MANAGEDSTRUCT(pmc)->ptr) { 
    90         struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; 
    91         void *ptr = PARROT_MANAGEDSTRUCT(pmc)->ptr; 
    92         void *newptr = mem_alloc_executable(jit->size); 
    93         if (!newptr) 
    94             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    95                     "Cannot allocate executable memory"); 
    96         memcpy(newptr, ptr, jit->size); 
    97         PARROT_MANAGEDSTRUCT(rv)->ptr = newptr; 
    98     } 
    99  
    100     return rv; 
    101 } 
    102  
    10312INTVAL 
    10413get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n) 
    10514{ 
     
    224133    } 
    225134} 
    226135 
    227 int 
    228 emit_is8bit(long disp) 
    229 { 
    230     return disp >= -128 && disp <= 127; 
    231 } 
    232  
    233 char * 
    234 emit_disp8_32(char *pc, int disp) 
    235 { 
    236     if (emit_is8bit(disp)) { 
    237         *(pc++) = (char)disp; 
    238         return pc; 
    239     } 
    240     else { 
    241         *(long *)pc = disp; 
    242         return pc + 4; 
    243     } 
    244 } 
    245  
    246 void 
    247 emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base) 
    248 { 
    249     int scale_byte; 
    250  
    251     switch (scale) { 
    252         case 1: 
    253             scale_byte = emit_Scale_1; 
    254             break; 
    255         case 2: 
    256             scale_byte = emit_Scale_2; 
    257             break; 
    258         case 4: 
    259             scale_byte = emit_Scale_4; 
    260             break; 
    261         case 8: 
    262             scale_byte = emit_Scale_8; 
    263             break; 
    264         default: 
    265             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    266                 "Invalid scale factor %d\n", scale); 
    267             return; 
    268     } 
    269  
    270     *pc = (char)(scale_byte | (i == emit_None ? emit_Index_None : emit_reg_Index(i)) | 
    271             emit_reg_Base(base)); 
    272 } 
    273  
    274 char * 
    275 emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp) 
    276 { 
    277     if (i && !scale) 
    278         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    279             "emit_r_X passed invalid scale+index combo\n"); 
    280  
    281     if (base == emit_EBP) { 
    282     /* modrm disp */ 
    283         if (i == emit_None) { 
    284             *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10) 
    285                     | reg_opcode | emit_reg_rm(emit_EBP)); 
    286             return emit_disp8_32(pc, disp); 
    287         } 
    288         /* modrm sib disp */ 
    289         else { 
    290             *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10) 
    291                     | reg_opcode | emit_b100); 
    292             emit_sib(interp, pc++, scale, i, base); 
    293             return emit_disp8_32(pc, disp); 
    294         } 
    295     } 
    296  
    297     /* modrm sib disp */ 
    298     if (base == emit_ESP) { 
    299         *(pc++) = (char)((emit_is8bit(disp) ? emit_Mod_b01 : emit_Mod_b10) 
    300                 | reg_opcode | emit_rm_b100); 
    301         emit_sib(interp, pc++, scale, i, emit_ESP); 
    302         return emit_disp8_32(pc, disp); 
    303     } 
    304  
    305     /* modrm disp32 */ 
    306     if (!base && !(i && scale)) { 
    307         *(pc++) = (char)(emit_Mod_b00 | reg_opcode | emit_rm_b101); 
    308         *(long *)pc = disp; 
    309         return pc + 4; 
    310     } 
    311  
    312     /* Ok, everything should be more regular here */ 
    313     *(pc++) = (char)((disp == 0 ? emit_Mod_b00 : 
    314               (emit_is8bit(disp) ? 
    315                emit_Mod_b01 : emit_Mod_b10)) | 
    316                reg_opcode | 
    317                (!base || (scale && i) ? emit_rm_b100 : emit_reg_rm(base))); 
    318  
    319     if (!base || (scale && i)) { 
    320         emit_sib(interp, pc++, scale, i, base); 
    321     } 
    322     if (disp) 
    323         pc = emit_disp8_32(pc, disp); 
    324  
    325     return pc; 
    326 } 
    327  
    328 char * 
    329 emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg) 
    330 { 
    331     if (opcode == emit_b000 && imm < 0) { 
    332         opcode = emit_b001;     /* -rol => 32 + ror */ 
    333         imm = -imm; 
    334     } 
    335  
    336     if (imm == 0) { 
    337         /* noop */ 
    338     } 
    339     else if (imm == 1) { 
    340         *(pc++) = (char) 0xd1; 
    341         *(pc++) = (char) emit_alu_X_r(opcode,  reg); 
    342     } 
    343     else if (imm > 1 && imm < 33) { 
    344         *(pc++) = (char) 0xc1; 
    345         *(pc++) = (char) emit_alu_X_r(opcode,  reg); 
    346         *(pc++) = (char)imm; 
    347     } 
    348     else { 
    349         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    350             "emit_shift_i_r passed invalid shift\n"); 
    351     } 
    352  
    353     return pc; 
    354 } 
    355  
    356 char * 
    357 emit_popl_r(char *pc, int reg) 
    358 { 
    359     *(pc++) = (char)(0x58 | (reg - 1)); 
    360     return pc; 
    361 } 
    362  
    363 unsigned char *lastpc; 
    364  
    365 size_t 
    366 calc_signature_needs(const char *sig, int *strings) 
    367 { 
    368     size_t stack_size = 0; 
    369     while (*sig) { 
    370         switch (*sig) { 
    371             case 't': 
    372                 (*strings)++; 
    373                 stack_size +=4; 
    374                 break; 
    375             case 'd': 
    376                 stack_size +=8; 
    377                 break; 
    378             default: 
    379                 stack_size +=4; 
    380                 break; 
    381         } 
    382         sig++; 
    383     } 
    384     return stack_size; 
    385  
    386 } 
    387  
    388136/* 
    389  * The function generated here is called as func(interp, nci_info) 
    390  * interp   ...  8(%ebp) 
    391  * nci_info ... 12(%ebp) 
    392  * 
    393  * The generate function for a specific signature looks quite similar to 
    394  * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles 
    395  * just compare the disassembly. 
    396  * 
    397  * If a non-NULL sizeptr is passed, the integer it points to will be written 
    398  * with the size of the allocated execmem buffer. 
    399  */ 
    400  
    401 void * 
    402 Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature, int *sizeptr) 
    403 { 
    404     char     *pc; 
    405     char     *execmem; 
    406     int       i                    = 0; 
    407     int       arg_count            = 0; 
    408     int       string_buffer_count  = 0; 
    409     const int ST_SIZE_OF           = 124; 
    410     const int JIT_ALLOC_SIZE       = 1024; 
    411  
    412     char      *signature_str      = Parrot_str_to_cstring(interp, signature); 
    413     /* skip over the result */ 
    414     char      *sig                = signature_str + 1; 
    415     size_t     stack_space_needed = calc_signature_needs(sig, 
    416                                         &string_buffer_count); 
    417  
    418     int base_offset        = 0; 
    419     int strings_offset     = base_offset - (sizeof (char *) * string_buffer_count); 
    420     int st_offset          = strings_offset - ST_SIZE_OF; 
    421     int args_offset        = st_offset - stack_space_needed; 
    422     int temp_calls_offset  = args_offset - 16; 
    423     int total_stack_needed = -temp_calls_offset; 
    424  
    425     /* 
    426      * ESP 
    427      * 0-15, 16 bytes for utility calls 
    428      * stack_space_needed for actual NCI call 
    429      * st 
    430      * STRINGS -> char * holding space 
    431      * EBP 
    432      */ 
    433  
    434     /* this ought to be enough - the caller of this function 
    435      * should free the function pointer returned here 
    436      */ 
    437     pc = execmem = (char *)mem_alloc_executable(JIT_ALLOC_SIZE); 
    438     if (! pc) 
    439         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    440                 "Cannot allocate executable memory"); 
    441  
    442  
    443     /* this generated jit function will be called as (INTERP (EBP 8), func_ptr 
    444     * (ESP 12), args signature (ESP 16)) */ 
    445  
    446     /* make stack frame, preserve %ebx */ 
    447     jit_emit_stack_frame_enter(pc); 
    448  
    449     emitm_subl_i_r(pc, total_stack_needed, emit_ESP); 
    450  
    451     /* Parrot_init_arg_nci(interp, &st, "S"); */ 
    452     /* args signature "S" */ 
    453     emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16); 
    454     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    455  
    456     /*&st*/ 
    457     emitm_lea_m_r(interp,  pc, emit_EAX, emit_EBP, 0, 1, st_offset); 
    458     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    459  
    460     /*interpreter*/ 
    461     emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); 
    462     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); 
    463  
    464     if (sig && *sig) 
    465       emitm_call_cfunc(pc, Parrot_init_arg_nci); 
    466  
    467     while (*sig) { 
    468         emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8); 
    469  
    470         switch (*sig) { 
    471             case '0':    /* null ptr or such - doesn't consume a reg */ 
    472                 jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX); 
    473                 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    474                 break; 
    475             case 'f': 
    476                 emitm_call_cfunc(pc, get_nci_N); 
    477                 emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset); 
    478                 break; 
    479             case 'N': 
    480             case 'd': 
    481                 emitm_call_cfunc(pc, get_nci_N); 
    482                 emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset); 
    483                 args_offset += 4; 
    484                 break; 
    485             case 'I':   /* INTVAL */ 
    486             case 'l':   /* long */ 
    487             case 'i':   /* int */ 
    488                 emitm_call_cfunc(pc, get_nci_I); 
    489                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    490                 break; 
    491             case 't':   /* string, pass a cstring */ 
    492                 emitm_call_cfunc(pc, get_nci_S); 
    493                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    494                 emitm_call_cfunc(pc, string_to_cstring_nullable); 
    495  
    496                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    497                 /* save off temporary allocation address */ 
    498                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset); 
    499                 strings_offset += 4; 
    500  
    501                 /* reset ESP(4) */ 
    502                 emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); 
    503                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    504                 break; 
    505             case 's':   /* short: movswl intreg_o(base), %eax */ 
    506                 emitm_call_cfunc(pc, get_nci_I); 
    507                 emitm_movswl_r_r(pc, emit_EAX, emit_EAX); 
    508                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    509                 break; 
    510             case 'c':   /* char: movsbl intreg_o(base), %eax */ 
    511                 emitm_call_cfunc(pc, get_nci_I); 
    512                 emitm_movsbl_r_r(pc, emit_EAX, emit_EAX); 
    513                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    514                 break; 
    515             case 'J':   /* interpreter */ 
    516                 emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); 
    517                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    518                 arg_count--; 
    519                 break; 
    520             case 'p':   /* push pmc->data */ 
    521                 emitm_call_cfunc(pc, get_nci_p); 
    522                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    523                 break; 
    524             case 'O':   /* push PMC * object in P2 */ 
    525             case 'P':   /* push PMC * */ 
    526             case '@': 
    527                 emitm_call_cfunc(pc, get_nci_P); 
    528                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    529                 break; 
    530             case 'v': 
    531                 break; 
    532             case 'b':   /* buffer (void*) pass Buffer_bufstart(SReg) */ 
    533                 emitm_call_cfunc(pc, get_nci_S); 
    534                 emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 
    535                                (size_t) &Buffer_bufstart((STRING *) NULL)); 
    536                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    537                 break; 
    538             case 'B':   /* buffer (void**) pass &Buffer_bufstart(SReg) */ 
    539                 emitm_call_cfunc(pc, get_nci_S); 
    540                 emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 
    541                               (size_t) &Buffer_bufstart((STRING *) NULL)); 
    542                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    543                 break; 
    544             case 'S': 
    545                 emitm_call_cfunc(pc, get_nci_S); 
    546                 emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset); 
    547                 break; 
    548  
    549  
    550             /* I have no idea how to handle these */ 
    551             case '2': 
    552             case '3': 
    553             case '4': 
    554             case 'V': 
    555                 mem_free_executable(execmem, JIT_ALLOC_SIZE); 
    556                 Parrot_str_free_cstring(signature_str); 
    557                 return NULL; 
    558                 break; 
    559             default: 
    560                 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    561                     "Unknown arg Signature %c\n", *sig); 
    562                 /* 
    563                  * oops unknown signature: 
    564                  * cleanup and try nci.c 
    565                  */ 
    566                 mem_free_executable(execmem, JIT_ALLOC_SIZE); 
    567                 Parrot_str_free_cstring(signature_str); 
    568                 return NULL; 
    569         } 
    570         args_offset +=4; 
    571         arg_count++; 
    572         sig++; 
    573     } 
    574  
    575     /* prepare to call VTABLE_get_pointer, set up args */ 
    576     /* interpreter - movl 8(%ebp), %eax */ 
    577     emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); 
    578     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); 
    579  
    580     /* pmc - movl 12(%ebp), %eax */ 
    581     emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12); 
    582     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    583  
    584     /* get the get_pointer() pointer from the pmc's vtable */ 
    585     emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(PMC, vtable)); 
    586     emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(VTABLE, get_pointer)); 
    587  
    588     /* call get_pointer(), result goes into eax */ 
    589     emitm_callr(pc, emit_EAX); 
    590     emitm_addl_i_r(pc, 16, emit_ESP); 
    591  
    592     /* call the resulting function pointer */ 
    593     emitm_callr(pc, emit_EAX); 
    594     emitm_subl_i_r(pc, 16, emit_ESP); 
    595  
    596     /* SAVE OFF EAX */ 
    597     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    598  
    599     /*&st*/ 
    600     emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); 
    601     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    602  
    603     /*interpreter*/ 
    604     emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8); 
    605     emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); 
    606  
    607     /* RESTORE BACK EAX */ 
    608     emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    609  
    610     /* now place return value in registers */ 
    611     /* first in signature is the return value */ 
    612     sig = signature_str; /* the result */ 
    613     switch (*sig) { 
    614         /* I have no idea how to handle these */ 
    615         case '2': 
    616         case '3': 
    617         case '4': 
    618             /* get integer from pointer - untested */ 
    619             emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0); 
    620             if (*sig == 2)      /* short */ 
    621                 emitm_movswl_r_r(pc, emit_EAX, emit_EAX); 
    622             emitm_call_cfunc(pc, set_nci_I); 
    623             break; 
    624         case 'f': 
    625         case 'd': 
    626             jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8); 
    627             emitm_call_cfunc(pc, set_nci_N); 
    628             /* pop num from st(0) and mov to reg */ 
    629             break; 
    630         case 's': 
    631             /* movswl %ax, %eax */ 
    632             emitm_movswl_r_r(pc, emit_EAX, emit_EAX); 
    633             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    634             emitm_call_cfunc(pc, set_nci_I); 
    635             break; 
    636         case 'c': 
    637             /* movsbl %al, %eax */ 
    638             emitm_movsbl_r_r(pc, emit_EAX, emit_EAX); 
    639             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    640             emitm_call_cfunc(pc, set_nci_I); 
    641             break; 
    642         case 'I':   /* INTVAL */ 
    643         case 'l': 
    644         case 'i': 
    645             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    646             emitm_call_cfunc(pc, set_nci_I); 
    647             break; 
    648         case 'v': /* void - do nothing */ 
    649             break; 
    650         case 'P': 
    651             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    652             emitm_call_cfunc(pc, set_nci_P); 
    653             break; 
    654         case 'p':   /* make a new unmanaged struct */ 
    655             /* save return value on stack */ 
    656  
    657             /* save pointer p */ 
    658             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12); 
    659  
    660             /* make new pmc */ 
    661             emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4); 
    662             emitm_call_cfunc(pc, pmc_new); 
    663  
    664             /* restore pointer p to EDX */ 
    665             emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12); 
    666  
    667             /* copy UnManagedStruct to stack for set_nci_P call */ 
    668             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    669  
    670             /* eax = PMC, get return value into edx */ 
    671             /* mov data(%eax), %eax 
    672                mov %edx, ptr(%eax) */ 
    673             emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data)); 
    674             emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, 
    675                            offsetof(struct Parrot_UnManagedStruct_attributes, ptr)); 
    676  
    677             /* reset EBP(4) */ 
    678             emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); 
    679             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    680  
    681             emitm_call_cfunc(pc, set_nci_P); 
    682             break; 
    683         case 'S': 
    684             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    685             emitm_call_cfunc(pc, set_nci_S); 
    686             break; 
    687         case 't':   /* string */ 
    688             /* EAX is char* */ 
    689             emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */ 
    690  
    691             /* overwrites address of st in EBP(4) */ 
    692             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    693  
    694             emitm_call_cfunc(pc, Parrot_str_new); 
    695  
    696             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8); 
    697  
    698             /* reset EBP(4) */ 
    699             emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset); 
    700             emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4); 
    701  
    702             emitm_call_cfunc(pc, set_nci_S); 
    703             break; 
    704         default: 
    705             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
    706                 "Unknown return Signature %c\n", *sig); 
    707             /* 
    708              * oops unknown signature: 
    709              * cleanup and try nci.c 
    710              */ 
    711             Parrot_str_free_cstring(signature_str); 
    712             mem_free_executable(execmem, JIT_ALLOC_SIZE); 
    713             return NULL; 
    714     } 
    715  
    716     /* free temporary strings */ 
    717     strings_offset = st_offset + ST_SIZE_OF; 
    718     for (i=0; i<string_buffer_count; i++) { 
    719         emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset); 
    720         emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0); 
    721         emitm_call_cfunc(pc, Parrot_str_free_cstring); 
    722         strings_offset += 4; 
    723     } 
    724  
    725     jit_emit_stack_frame_leave(pc); 
    726     emitm_ret(pc); 
    727     PARROT_ASSERT(pc - execmem <= JIT_ALLOC_SIZE); 
    728  
    729     if (sizeptr) 
    730         *sizeptr = JIT_ALLOC_SIZE; 
    731     Parrot_str_free_cstring(signature_str); 
    732     return (void *)D2FPTR(execmem); 
    733 } 
    734  
    735 /* 
    736137 * Local variables: 
    737138 *   c-file-style: "parrot" 
    738139 * End: 
  • src/frame_builder.h

     
    11/* 
    22 * Copyright (C) 2002-2009, Parrot Foundation. 
    3  */ 
    4  
    5 /* 
     3 * 
    64 * frame_builder.h 
    75 * 
    8  * i386 
    9  * 
    106 * $Id$ 
    117 */ 
    128 
    13 #ifndef PARROT_I386_JIT_EMIT_H_GUARD 
    14 #define PARROT_I386_JIT_EMIT_H_GUARD 
     9#ifndef PARROT_FRAME_BUILDER_H_GUARD 
     10#define PARROT_FRAME_BUILDER_H_GUARD 
    1511 
    1612#if defined(__cplusplus) 
    1713#  define EXTERN extern "C" 
     
    2117 
    2218#include <assert.h> 
    2319#include "parrot/parrot.h" 
    24 #include "parrot/hash.h" 
    25 #include "parrot/oplib/ops.h" 
    2620 
    2721/* 
    2822 * NCI interface 
    2923 */ 
     24 
    3025void * 
    31 Parrot_jit_build_call_func(Interp *, PMC *, STRING *, int *); 
     26Parrot_jit_build_call_func(Interp *, PMC *, STRING *, void **); 
    3227 
    3328/* custom pmc callback functions */ 
    3429void 
     
    3732PMC* 
    3833Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv); 
    3934 
    40 struct jit_buffer_private_data { 
    41     int size; 
    42 }; 
    43  
    44 /* Scale factor values */ 
    45 #define emit_Scale(scale) ((scale) << 6) 
    46 #define emit_Scale_1 emit_Scale(0) 
    47 #define emit_Scale_2 emit_Scale(1) 
    48 #define emit_Scale_4 emit_Scale(2) 
    49 #define emit_Scale_8 emit_Scale(3) 
    50  
    51 /* ESIB byte */ 
    52 #define emit_reg_Index(x) (((x)-1) << 3) 
    53 #define emit_reg_Base(x) ((x)-1) 
    54 #define emit_Index_None ((emit_b100) << 3) 
    55  
    5635/* 
    5736 * helper funcs - get argument n 
    5837 */ 
     
    9271 
    9372void set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val); 
    9473 
    95 /* 
    96  * if we have a delegated method like typeof_i_p, that returns an INTVAL 
    97  * and that is all in a sequence of JITted opcodes, and when these INTVAL 
    98  * is MAPped, we got a problem. So the EXT_CALL flag is disabled - mapped 
    99  * registers are saved/restored around vtable calls. 
    100  */ 
    101 #define  JIT_VTABLE_OPS 1 
     74#endif /* PARROT_FRAME_BUILDER_H_GUARD */ 
    10275 
    103 /* EXEC_SHARED generates code to be used with libparrot.so 
    104  * It grabs the real address of cgp_core from the gcc generated code 
    105  * x/1i cgp_code 
    106  *     jmp *0xXXXX 
    107  * x/1wx 0xXXXX 
    108  *     real address of cpg_core 
    109  * s. exec_emit_end 
    110  * XXX This should be a command line option. 
    111  */ 
    112 #undef EXEC_SHARED 
    113  
    114 extern UINTVAL ld(UINTVAL); 
    115  
    116 #define NEG_MINUS_ZERO 
    117 /* #define NEG_ZERO_SUB */ 
    118  
    119 /* Register codes */ 
    120 #define emit_None 0 
    121  
    122 /* These are + 1 the real values */ 
    123 #define emit_EAX 1 
    124 #define emit_ECX 2 
    125 #define emit_EDX 3 
    126 #define emit_EBX 4 
    127 #define emit_ESP 5 
    128 #define emit_EBP 6 
    129 #define emit_ESI 7 
    130 #define emit_EDI 8 
    131  
    132 /* Scratch register. */ 
    133  
    134 #define ISR1 emit_EAX 
    135 #define FSR1 0 
    136  
    137 #define emit_b00 0 
    138 #define emit_b01 1 
    139 #define emit_b10 2 
    140 #define emit_b11 3 
    141  
    142 #define emit_b000 0 
    143 #define emit_b001 1 
    144 #define emit_b010 2 
    145 #define emit_b011 3 
    146 #define emit_b100 4 
    147 #define emit_b101 5 
    148 #define emit_b110 6 
    149 #define emit_b111 7 
    150  
    151 /* Mod R/M byte */ 
    152 #define emit_reg(x) ((x) << 3) 
    153 #define emit_Mod(Mod) ((Mod) << 6) 
    154 #define emit_reg_rm(x) ((x)-1) 
    155  
    156 /* Mod values for Mod R/M Byte */ 
    157 #define emit_Mod_b00 emit_Mod(emit_b00) 
    158 #define emit_Mod_b01 emit_Mod(emit_b01) 
    159 #define emit_Mod_b10 emit_Mod(emit_b10) 
    160  
    161 /* special R/M values */ 
    162 #define emit_rm_b101 emit_b101 
    163 #define emit_rm_b100 emit_b100 
    164  
    165 #define emit_r_m(interp, pc, reg1, b, i, s, d) \ 
    166     emit_r_X((interp), (pc), emit_reg((reg1)-1), (b), (i), (s), (d)) 
    167  
    168 #define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1)) 
    169  
    170 #define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2)) 
    171  
    172 int emit_is8bit(long disp); 
    173  
    174 char * emit_disp8_32(char *pc, int disp); 
    175  
    176 void emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base); 
    177  
    178 char * emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, 
    179     int scale, long disp); 
    180  
    181 char * emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg); 
    182  
    183 char * emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm, 
    184                int base, int i, int scale, long disp); 
    185  
    186 char * emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2); 
    187  
    188 char * emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg, 
    189                int base, int i, int scale, long disp); 
    190  
    191 /* CDQ - need this to do multiply */ 
    192 #define emitm_cdq(pc) *((pc)++) = (char) 0x99 
    193  
    194 /* RET */ 
    195 #define emitm_ret(pc) *((pc)++) = (char) 0xc3 
    196  
    197 /* NOP */ 
    198 #define emit_nop(pc) *((pc)++) = (char) 0x90 
    199  
    200 /* PUSHes */ 
    201  
    202 #define emitm_pushl_r(pc, reg) \ 
    203     *((pc)++) = (char) 0x50 | ((reg) - 1) 
    204  
    205 #define emitm_pushl_i(pc, imm) { \ 
    206     *((pc)++) = (char) 0x68; \ 
    207     *(long *)(pc) = (long)(imm); \ 
    208     (pc) += 4; } 
    209  
    210 #define emitm_pushl_m(pc, mem) { \ 
    211        *((pc)++) = (char) 0xff; \ 
    212        *((pc)++) = (char) 0x35; \ 
    213        *(long *)(pc) = (long)(mem); \ 
    214        (pc) += 4; } 
    215  
    216 char * emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale, 
    217     long disp); 
    218  
    219 /* POPs */ 
    220  
    221 char * emit_popl_r(char *pc, int reg); 
    222  
    223 #  define emitm_popl_r(pc, reg) \ 
    224     (pc) = emit_popl_r((pc), (reg)) 
    225  
    226 char * emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale, 
    227     long disp); 
    228  
    229 /* MOVes */ 
    230  
    231 char * emit_movb_r_r(char *pc, int reg1, int reg2); 
    232  
    233 #  define jit_emit_mov_rr_i(pc, reg2, reg1) if ((reg1) != (reg2)) { \ 
    234     *((pc)++) = (char) 0x89; \ 
    235     *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); } 
    236  
    237 #  define jit_emit_mov_ri_i(interp, pc, reg, imm) { \ 
    238     *((pc)++) = (char)(0xb8 | ((reg) - 1)); \ 
    239     *(long *)(pc) = (long)(imm); (pc) += 4; } 
    240  
    241 #  define emitm_movX_Y_Z(interp, op, pc, reg1, b, i, s, d) { \ 
    242     *((pc)++) = (char) (op); \ 
    243     (pc) = emit_r_m((interp), (pc), (reg1), (b), (i), (s), (long)(d)); } 
    244  
    245 #  define emitm_movb_r_m(interp, pc, reg1, b, i, s, d) \ 
    246     emitm_movX_Y_Z((interp), 0x88, (pc), (reg1), (b), (i), (s), (d)) 
    247  
    248 #  define emitm_movl_r_m(interp, pc, reg1, b, i, s, d) \ 
    249     emitm_movX_Y_Z((interp), 0x89, (pc), (reg1), (b), (i), (s), (d)) 
    250  
    251 /* move byte/word with sign extension */ 
    252 #  define emitm_movsbl_r_m(interp, pc, reg1, b, i, s, d) { \ 
    253     *((pc)++) = (char) 0x0f; \ 
    254     emitm_movX_Y_Z((interp), 0xBE, (pc), (reg1), (b), (i), (s), (d)); \ 
    255 } 
    256  
    257 #  define emitm_movswl_r_m(interp, pc, reg1, b, i, s, d) { \ 
    258     *((pc)++) = (char) 0x0f; \ 
    259     emitm_movX_Y_Z((interp), 0xBF, (pc), (reg1), (b), (i), (s), (d)); \ 
    260 } 
    261  
    262 #  define emitm_movsbl_r_r(pc, reg1, reg2) { \ 
    263     *((pc)++) = (char) 0x0f; \ 
    264     *((pc)++) = (char) 0xbe; \ 
    265     *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \ 
    266 } 
    267  
    268 #  define emitm_movswl_r_r(pc, reg1, reg2) { \ 
    269     *((pc)++) = (char) 0x0f; \ 
    270     *((pc)++) = (char) 0xbf; \ 
    271     *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); \ 
    272 } 
    273  
    274 #  define emitm_movb_m_r(interp, pc, reg1, b, i, s, d) \ 
    275     emitm_movX_Y_Z((interp), 0x8a, (pc), (reg1), (b), (i), (s), (d)) 
    276  
    277 #  define emitm_movl_m_r(interp, pc, reg1, b, i, s, d) \ 
    278     emitm_movX_Y_Z((interp), 0x8b, (pc), (reg1), (b), (i), (s), (d)) 
    279  
    280 #  define emitm_lea_m_r(interp, pc, reg1, b, i, s, d) \ 
    281     emitm_movX_Y_Z((interp), 0x8d, (pc), (reg1), (b), (i), (s), (d)) 
    282  
    283 char * emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i, 
    284     int scale, long disp); 
    285  
    286 #  define emitm_movl_i_m(pc, imm, b, i, s, d) { \ 
    287     *((pc)++) = (char) 0xc7; \ 
    288     (pc) = emit_r_X((interp), (pc), emit_reg(emit_b000), (b), (i), (s), (long)(d)); \ 
    289     *(long *)(pc) = (long)(imm); (pc) += 4; } 
    290  
    291 /* Various ALU formats */ 
    292  
    293 #  define emitm_alul_r_r(pc, op, reg1, reg2) { \ 
    294     *((pc)++) = (char) (op); *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); } 
    295  
    296 #  define emitm_alub_i_r(pc, op1, op2, imm, reg) { \ 
    297     *((pc)++) = (char) (op1); *((pc)++) = (char) emit_alu_X_r((op2), (reg)); *((pc)++) = (char)(imm); } 
    298  
    299 #  define emitm_alul_i_r(pc, op1, op2, imm, reg) { \ 
    300     *((pc)++) = (char) (op1); \ 
    301     *((pc)++) = (char) emit_alu_X_r((op2), (reg)); \ 
    302     *(long *)((pc)) = (long)(imm); (pc) += 4; } 
    303  
    304 #  define emitm_alul_i_m(pc, op1, op2, imm, b, i, s, d) { \ 
    305     *((pc)++) = (char) (op1); \ 
    306     (pc) = emit_r_X((interp), (pc), emit_reg(op2), (b), (i), (s), (d)); \ 
    307     *(long *)(pc) = (long)(imm); (pc) += 4; } 
    308  
    309 #  define emitm_alul_r_m(pc, op, reg, b, i, s, d) { \ 
    310     *((pc)++) = (char) (op); \ 
    311     (pc) = emit_r_X((interp), (pc), emit_reg((reg)-1), (b), (i), (s), (long)(d)); } 
    312  
    313 /* ADDs */ 
    314  
    315 #  define emitm_addb_r_r(pc, reg1, reg2) \ 
    316     emitm_alul_r_r((pc), 0x00, (reg1), (reg2)) 
    317  
    318 #  define emitm_addb_i_r(pc, imm, reg) \ 
    319     emitm_alub_i_r((pc), 0x83, emit_b000, (imm), (reg)) 
    320  
    321 #  define jit_emit_add_rr_i(interp, pc, reg1, reg2) \ 
    322     emitm_alul_r_r((pc), 0x01, (reg2), (reg1)) 
    323  
    324 #  define jit_emit_add_ri_i(interp, pc, reg, imm)   \ 
    325     emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg)) 
    326  
    327 #  define emitm_addl_i_r(pc, imm, reg)   \ 
    328     emitm_alul_i_r((pc), 0x81, emit_b000, (imm), (reg)) 
    329  
    330 #  define emitm_addl_i_m(pc, imm, b, i, s, d) \ 
    331     emitm_alul_i_m((pc), 0x81, emit_b000, (imm), (b), (i), (s), (d)) 
    332  
    333 #  define emitm_addl_r_m(pc, reg, b, i, s, d) \ 
    334     emitm_alul_r_m((pc), 0x01, (reg), (b), (i), (s), (d)) 
    335  
    336 #  define emitm_addl_m_r(pc, reg, b, i, s, d) \ 
    337     emitm_alul_r_m((pc), 0x03, (reg), (b), (i), (s), (d)) 
    338  
    339 /* SUBs */ 
    340  
    341 #  define jit_emit_sub_rr_i(interp, pc, reg1, reg2) \ 
    342     emitm_alul_r_r((pc), 0x29, (reg2), (reg1)) 
    343  
    344 #  define emitm_subl_i_r(pc, imm, reg) \ 
    345     emitm_alul_i_r((pc), 0x81, emit_b101, (imm), (reg)) 
    346  
    347 #  define jit_emit_sub_ri_i(interp, pc, r, i) emitm_subl_i_r((pc), (i), (r)) 
    348  
    349 #  define emitm_subl_r_m(pc, reg, b, i, s, d) \ 
    350     emitm_alul_r_m((pc), 0x29, (reg), (b), (i), (s), (d)) 
    351  
    352 #  define emitm_subl_m_r(pc, reg, b, i, s, d) \ 
    353     emitm_alul_r_m((pc), 0x2b, (reg), (b), (i), (s), (d)) 
    354  
    355 #  define emitm_subl_i_m(pc, imm, b, i, s, d) \ 
    356     emitm_alul_i_m((pc), 0x81, emit_b101, (imm), (b), (i), (s), (d)) 
    357  
    358 /* These are used by both signed and unsigned EDIV, but only unsigned MUL */ 
    359 #  define emitm_alu_imp_r(pc, op, reg) { \ 
    360     *((pc)++) = (char) 0xf7; \ 
    361     *((pc)++) = (char) emit_alu_X_r((op), (reg)); } 
    362  
    363 #  define emitm_alu_imp_m(pc, op, b, i, s, d) { \ 
    364     *((pc)++) = (char) 0xf7; \ 
    365     (pc) = emit_r_X((interp), (pc), emit_reg(op), (b), (i), (s), (d)); } 
    366  
    367 /* Unsigned MUL and EDIV */ 
    368 /* EAX implicit destination in multiply and divide */ 
    369  
    370 #  define emitm_umull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b100, (reg2)) 
    371  
    372 #  define emitm_udivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b110, (reg2)) 
    373  
    374 #  define emitm_umull_m(pc, b, i, s, d) \ 
    375     emitm_alu_imp_m((pc), emit_b100, (b), (i), (s), (d)) 
    376  
    377 #  define emitm_udivl_m(pc, b, i, s, d) \ 
    378     emitm_alu_imp_m((pc), emit_b110, (b), (i), (s), (d)) 
    379  
    380 /* Signed MUL and EDIV */ 
    381  
    382 #  define emitm_sdivl_r(pc, reg2) emitm_alu_imp_r((pc), emit_b111, (reg2)) 
    383  
    384 #  define emitm_sdivl_m(pc, b, i, s, d) \ 
    385     emitm_alu_imp_m((pc), emit_b111, (b), (i), (s), (d)) 
    386  
    387 #  define jit_emit_cdq(pc) *(pc)++ = 0x99 
    388  
    389 /* TEST for zero */ 
    390 #  define jit_emit_test_r_i(pc, reg1) emitm_alul_r_r((pc), 0x85, (reg1), (reg1)) 
    391  
    392 #  define emitm_smull_r(pc, reg2) emitm_alu_imp_r((pc), emit_b101, (reg2)) 
    393  
    394 #  define jit_emit_mul_rr_i(interp, pc, reg1, reg2) { \ 
    395     *(pc)++ = 0xf; \ 
    396     emitm_alul_r_r((pc), 0xaf, (reg1), (reg2)); } 
    397  
    398 #  define emitm_smull_r_m(pc, reg1, b, i, s, d) { \ 
    399     *(pc)++ = 0xf; \ 
    400     emitm_alul_r_m((pc), 0xaf, (reg1), (b), (i), (s), (d)); } 
    401  
    402 char * opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src); 
    403  
    404 #  define jit_emit_mul_rir_i(pc, dest, imm, src) \ 
    405        (pc) = opt_mul(interp, (pc), (dest), (imm), (src)) 
    406  
    407  
    408 #  define jit_emit_mul_ri_i(pc, r, imm) jit_emit_mul_rir_i((pc), (r), (imm), (r)) 
    409  
    410 #  define jit_emit_mul_RIM_ii(pc, reg, imm, ofs) \ 
    411     emitm_alul_r_m((pc), 0x69, (reg), emit_EBX, emit_None, 1, (ofs)); \ 
    412     *(long *)(pc) = (long)(imm); \ 
    413     (pc) += 4; 
    414  
    415 /* NEG */ 
    416  
    417 #  define jit_emit_neg_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b011, (reg)) 
    418  
    419 #  define emitm_negl_m(pc, b, i, s, d) \ 
    420     emitm_alu_imp_m((pc), emit_b011, (b), (i), (s), (d)) 
    421  
    422 /* AND */ 
    423  
    424 #  define emit_andl_r_r(pc, reg1, reg2) emitm_alul_r_r((pc), 0x21, (reg1), (reg2)) 
    425 #  define jit_emit_band_rr_i(interp, pc, r1, r2) emit_andl_r_r((pc), (r2), (r1)) 
    426  
    427 #  define jit_emit_band_ri_i(interp, pc, reg, imm)  \ 
    428     emitm_alul_i_r((pc), 0x81, emit_b100, (imm), (reg)) 
    429  
    430 #  define emitm_andl_r_m(pc, reg, b, i, s, d) \ 
    431     emitm_alul_r_m((pc), 0x21, (reg), (b), (i), (s), (d)) 
    432  
    433 #  define emitm_andl_m_r(pc, reg, b, i, s, d) \ 
    434     emitm_alul_r_m((pc), 0x23, (reg), (b), (i), (s), (d)) 
    435  
    436 #  define emitm_andl_i_m(pc, imm, b, i, s, d) \ 
    437     emitm_alul_i_m((pc), 0x81, emit_b100, (imm), (b), (i), (s), (d)) 
    438  
    439 /* TEST op */ 
    440 #  define jit_emit_test_rr_i(pc, r1, r2) emitm_alul_r_r((pc), 0x85, (r1), (r2)) 
    441  
    442 #  define jit_emit_test_ri_i(pc, r, im)  \ 
    443            emitm_alul_i_r((pc), 0xF7, emit_b000, (im), (r)) 
    444  
    445 #  define jit_emit_test_RM_i(pc, r, offs)  \ 
    446            emitm_alul_r_m((pc), 0x85, (r), emit_EBX, 0, 1, (offs)) 
    447  
    448 /* OR */ 
    449  
    450 #  define jit_emit_bor_rr_i(interp, pc, reg1, reg2) emitm_alul_r_r((pc), 0x9, (reg2), (reg1)) 
    451  
    452 #  define jit_emit_bor_ri_i(interp, pc, reg, imm) \ 
    453     emitm_alul_i_r((pc), 0x81, emit_b001, (imm), (reg)) 
    454  
    455 #  define emitm_orl_r_m(pc, reg, b, i, s, d) \ 
    456     emitm_alul_r_m((pc), 0x09, (reg), (b), (i), (s), (d)) 
    457  
    458 #  define emitm_orl_m_r(pc, reg, b, i, s, d) \ 
    459     emitm_alul_r_m((pc), 0x0b, (reg), (b), (i), (s), (d)) 
    460  
    461 #  define emitm_orl_i_m(pc, imm, b, i, s, d) \ 
    462     emitm_alul_i_m((pc), 0x81, emit_b001, (imm), (b), (i), (s), (d)) 
    463  
    464 /* XOR */ 
    465  
    466 #  define jit_emit_bxor_rr_i(interp, pc, reg1, reg2) \ 
    467     emitm_alul_r_r((pc), 0x31, (reg2), (reg1)) 
    468  
    469 #  define jit_emit_bxor_ri_i(intepr, pc, reg, imm) \ 
    470     emitm_alul_i_r((pc), 0x81, emit_b110, (imm), (reg)) 
    471  
    472 #  define emitm_xorl_r_m(pc, reg, b, i, s, d) \ 
    473     emitm_alul_r_m((pc), 0x31, (reg), (b), (i), (s), (d)) 
    474  
    475 #  define emitm_xorl_m_r(pc, reg, b, i, s, d) \ 
    476     emitm_alul_r_m((pc), 0x33, (reg), (b), (i), (s), (d)) 
    477  
    478 #  define emitm_xorl_i_m(pc, imm, b, i, s, d) \ 
    479     emitm_alul_i_m((pc), 0x81, emit_b110, (imm), (b), (i), (s), (d)) 
    480  
    481 /* NOT */ 
    482  
    483 #  define jit_emit_not_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b010, (reg)) 
    484 #  define emitm_notl_m(pc, b, i, s, d) \ 
    485     emitm_alu_imp_m((pc), emit_b010, (b), (i), (s), (d)) 
    486  
    487 #  define jit_emit_not_M_i(interp, pc, offs) emitm_notl_m((pc), emit_EBX, 0, 1, (offs)) 
    488  
    489 /* XCHG */ 
    490 #  define jit_emit_xchg_rr_i(interp, pc, r1, r2) { \ 
    491     if ((r1) != (r2)) { \ 
    492     *((pc)++) = (char) 0x87; \ 
    493     *((pc)++) = (char) emit_alu_r_r((r1), (r2)); \ 
    494     } \ 
    495 } 
    496  
    497 #  define jit_emit_xchg_rm_i(pc, r, m) { \ 
    498     emitm_alul_r_m((pc), 0x87, (r), emit_None, emit_None, emit_None, (m)) \ 
    499 } 
    500 #  define jit_emit_xchg_RM_i(interp, pc, r, offs) { \ 
    501     emitm_alul_r_m((pc), 0x87, (r), emit_EBX, emit_None, 1, (offs)) \ 
    502 } 
    503 #  define jit_emit_xchg_MR_i(interp, pc, offs, r) jit_emit_xchg_RM_i((interp), (pc), (r), (offs)) 
    504  
    505 /* SHL */ 
    506  
    507 #  define jit_emit_shl_ri_i(interp, pc, reg, imm) \ 
    508     { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); } 
    509  
    510 #  define emitm_shll_i_m(pc, imm, b, i, s, d) \ 
    511     { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); } 
    512  
    513 #  define emitm_shll_r_r(interp, pc, reg1, reg2) \ 
    514     { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); } 
    515  
    516 #  define emitm_shll_r_m(pc, reg, b, i, s, d) \ 
    517     { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); } 
    518  
    519 /* SHR */ 
    520  
    521 #  define jit_emit_lsr_ri_i(interp, pc, reg, imm) \ 
    522     { (pc) = emit_shift_i_r((interp), (pc), emit_b101, (imm), (reg)); } 
    523  
    524 #  define emitm_shrl_i_m(pc, imm, b, i, s, d) \ 
    525     { (pc) = emit_shift_i_m((pc), emit_b101, (imm), (b), (i), (s), (d)); } 
    526  
    527 #  define emitm_shrl_r_r(interp, pc, reg1, reg2) \ 
    528     { (pc) = emit_shift_r_r((interp), (pc), emit_b101, (reg1), (reg2)); } 
    529  
    530 #  define emitm_shrl_r_m(pc, reg, b, i, s, d) \ 
    531     { (pc) = emit_shift_r_m((pc), emit_b101, (reg), (b), (i), (s), (d)); } 
    532  
    533 /* SAL */ 
    534  
    535 #  define emitm_sall_i_r(interp, pc, imm, reg) \ 
    536     { (pc) = emit_shift_i_r((interp), (pc), emit_b100, (imm), (reg)); } 
    537  
    538 #  define emitm_sall_i_m(pc, imm, b, i, s, d) \ 
    539     { (pc) = emit_shift_i_m((pc), emit_b100, (imm), (b), (i), (s), (d)); } 
    540  
    541 #  define emitm_sall_r_r(interp, pc, reg1, reg2) \ 
    542     { (pc) = emit_shift_r_r((interp), (pc), emit_b100, (reg1), (reg2)); } 
    543  
    544 #  define emitm_sall_r_m(pc, reg, b, i, s, d) \ 
    545     { (pc) = emit_shift_r_m((pc), emit_b100, (reg), (b), (i), (s), (d)); } 
    546  
    547 /* SAR */ 
    548  
    549 #  define jit_emit_shr_ri_i(interp, pc, reg, imm) \ 
    550     { (pc) = emit_shift_i_r((interp), (pc), emit_b111, (imm), (reg)); } 
    551  
    552  
    553 #  define emitm_sarl_i_m(pc, imm, b, i, s, d) \ 
    554     { (pc) = emit_shift_i_m((pc), emit_b111, (imm), (b), (i), (s), (d)); } 
    555  
    556 #  define emitm_sarl_r_r(interp, pc, reg1, reg2) \ 
    557     { (pc) = emit_shift_r_r((interp), (pc), emit_b111, (reg1), (reg2)); } 
    558  
    559 #  define emitm_sarl_r_m(pc, reg, b, i, s, d) \ 
    560     { (pc) = emit_shift_r_m((pc), emit_b111, (reg), (b), (i), (s), (d)); } 
    561  
    562 /* rotate */ 
    563  
    564 #  define jit_emit_rol_ri_i(interp, pc, reg, imm) \ 
    565     { (pc) = emit_shift_i_r((interp), (pc), emit_b000, (imm), (reg)); } 
    566  
    567 #  define jit_emit_ror_ri_i(interp, pc, reg, imm) \ 
    568     { (pc) = emit_shift_i_r((interp), (pc), emit_b001, (imm), (reg)); } 
    569  
    570 /* interface, shift r1 by r2 bits */ 
    571  
    572 #  define jit_emit_shl_rr_i(interp, pc, r1, r2) \ 
    573     (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b100) 
    574  
    575 #  define jit_emit_shl_RM_i(interp, pc, r1, offs)  \ 
    576     (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b100) 
    577  
    578 /* shr seems to be the arithmetic shift */ 
    579 #  define jit_emit_shr_rr_i(interp, pc, r1, r2)  \ 
    580     (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b111) 
    581  
    582 #  define jit_emit_shr_RM_i(interp, pc, r1, offs)  \ 
    583     (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b111) 
    584  
    585 #  define jit_emit_lsr_rr_i(interp, pc, r1, r2)  \ 
    586     (pc) = opt_shift_rr((interp), jit_info, (r1), (r2), emit_b101) 
    587  
    588 #  define jit_emit_lsr_RM_i(interp, pc, r1, offs)  \ 
    589     (pc) = opt_shift_rm((interp), jit_info, (r1), (offs), emit_b101) 
    590  
    591 /* MOV (reg), reg */ 
    592 #  define emit_movm_r_r(pc, src, dest) \ 
    593     *((pc)++) = (char) 0x8b; \ 
    594     *((pc)++) = (char) (src) | (dest) << 3 
    595  
    596 /* MOV X(reg), reg */ 
    597 #  define emit_movb_i_r_r(pc, imm, src, dest) \ 
    598     *((pc)++) = (char)(0x8b); \ 
    599     *((p)c++) = (char)(0x40 | ((src) - 1) | ((dest) - 1) << 3); \ 
    600     *((pc)++) = (imm) 
    601  
    602 /* INC / DEC */ 
    603 #  define jit_emit_inc_r_i(pc, reg) *((pc)++) = (char)(0x40 | ((reg) - 1)) 
    604 #  define jit_emit_dec_r_i(pc, reg) *((pc)++) = (char)(0x48 | ((reg) - 1)) 
    605  
    606 /* Floating point ops */ 
    607  
    608 #  define emitm_floatop 0xd8  /* 11011000 */ 
    609 #  define jit_emit_dec_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF6; } 
    610 #  define jit_emit_inc_fsp(pc) { *((pc)++) = (char) 0xD9; *((pc)++) = (char) 0xF7; } 
    611  
    612 #  define emitm_fl_2(interp, pc, mf, opa, opb, b, i, s, d) { \ 
    613     *((pc)++) = (char)(emitm_floatop | ((mf) << 1) | (opa)); \ 
    614     (pc) = emit_r_X((interp), (pc), emit_reg(opb), (b), (i), (s), (long)(d)); } 
    615  
    616 #  define emitm_fl_3(pc, d_p_opa, opb_r, sti) { \ 
    617     *((pc)++) = (char)(emitm_floatop | (d_p_opa)); \ 
    618     *((pc)++) = (char)(0xc0 | ((opb_r) << 3) | (sti)); } 
    619  
    620 #  define emitm_fl_4(pc, op) { \ 
    621     *((pc)++) = (char)(emitm_floatop | emit_b001); \ 
    622     *((pc)++) = (char)(0xe0 | (op)); } 
    623  
    624 /* Integer loads and stores */ 
    625 #  define emitm_fildl(interp, pc, b, i, s, d) \ 
    626     emitm_fl_2((interp), (pc), emit_b01, 1, emit_b000, (b), (i), (s), (d)) 
    627  
    628 #  define emitm_fistpl(interp, pc, b, i, s, d) \ 
    629     emitm_fl_2((interp), (pc), emit_b01, 1, emit_b011, (b), (i), (s), (d)) 
    630  
    631 #  define emitm_fistl(interp, pc, b, i, s, d) \ 
    632     emitm_fl_2((interp), (pc), emit_b01, 1, emit_b010, (b), (i), (s), (d)) 
    633  
    634 /* long long integer load/store */ 
    635 #  define emitm_fildll(interp, pc, b, i, s, d) \ 
    636     emitm_fl_2((interp), (pc), emit_b11, 1, emit_b101, (b), (i), (s), (d)) 
    637  
    638 #  define emitm_fistpll(interp, pc, b, i, s, d) \ 
    639     emitm_fl_2((interp), (pc), emit_b11, 1, emit_b111, (b), (i), (s), (d)) 
    640  
    641 /* Double loads and stores */ 
    642 #  define emitm_fldl(interp, pc, b, i, s, d) \ 
    643     emitm_fl_2((interp), (pc), emit_b10, 1, emit_b000, (b), (i), (s), (d)) 
    644  
    645 #  define emitm_fstpl(interp, pc, b, i, s, d) \ 
    646     emitm_fl_2((interp), (pc), emit_b10, 1, emit_b011, (b), (i), (s), (d)) 
    647  
    648 #  define emitm_fstl(interp, pc, b, i, s, d) \ 
    649     emitm_fl_2((interp), (pc), emit_b10, 1, emit_b010, (b), (i), (s), (d)) 
    650  
    651 /* long double load / store */ 
    652 #  define emitm_fldt(interp, pc, b, i, s, d) \ 
    653     emitm_fl_2((interp), (pc), emit_b01, 1, emit_b101, (b), (i), (s), (d)) 
    654  
    655 #  define emitm_fstpt(interp, pc, b, i, s, d) \ 
    656     emitm_fl_2((interp), (pc), emit_b01, 1, emit_b111, (b), (i), (s), (d)) 
    657  
    658 /* short float load / store */ 
    659 #  define emitm_flds(interp, pc, b, i, s, d) \ 
    660     emitm_fl_2((interp), (pc), emit_b00, 1, emit_b000, (b), (i), (s), (d)) 
    661  
    662 #  define emitm_fstps(interp, pc, b, i, s, d) \ 
    663     emitm_fl_2((interp), (pc), emit_b00, 1, emit_b010, (b), (i), (s), (d)) 
    664  
    665 #if NUMVAL_SIZE == 8 
    666  
    667 #  define jit_emit_fload_m_n(interp, pc, address) \ 
    668       emitm_fldl((interp), (pc), emit_None, emit_None, emit_None, (address)) 
    669  
    670 #  define jit_emit_fload_mb_n(interp, pc, base, offs) \ 
    671       emitm_fldl((interp), (pc), (base), emit_None, 1, (offs)) 
    672  
    673 #  define jit_emit_fstore_m_n(interp, pc, address) \ 
    674       emitm_fstpl((interp), (pc), emit_None, emit_None, emit_None, (address)) 
    675  
    676 #  define jit_emit_fstore_mb_n(interp, pc, base, offs) \ 
    677       emitm_fstpl((interp), (pc), (base), emit_None, 1, (offs)) 
    678  
    679 #  define jit_emit_fst_mb_n(interp, pc, base, offs) \ 
    680       emitm_fstl((interp), (pc), (base), emit_None, 1, (offs)) 
    681  
    682 #else /* NUMVAL_SIZE */ 
    683  
    684 #  define jit_emit_fload_m_n(interp, pc, address) \ 
    685       emitm_fldt((pc), emit_None, emit_None, emit_None, (address)) 
    686  
    687 #  define jit_emit_fload_mb_n(interp, pc, base, offs) \ 
    688       emitm_fldt((pc), (base), emit_None, 1, (offs)) 
    689  
    690 #  define jit_emit_fstore_m_n(pc, address) \ 
    691       emitm_fstpt((pc), emit_None, emit_None, emit_None, (address)) 
    692  
    693 #  define jit_emit_fstore_mb_n(interp, pc, base, offs) \ 
    694       emitm_fstpt((pc), (base), emit_None, 1, (offs)) 
    695  
    696 #  define jit_emit_fst_mb_n(interp, pc, base, offs) \ 
    697       emitm_fstt((pc), (base), emit_None, 1, (offs)) 
    698  
    699 #endif /* NUMVAL_SIZE */ 
    700  
    701 #if INTVAL_SIZE == 4 
    702  
    703 #  define jit_emit_fload_m_i(interp, pc, address) \ 
    704       emitm_fildl((interp), (pc), emit_None, emit_None, emit_None, (address)) 
    705 #  define jit_emit_fload_mb_i(interp, pc, offs) \ 
    706       emitm_fildl((interp), (pc), emit_EBX, emit_None, 1, (offs)) 
    707 #  define jit_emit_fstore_m_i(pc, m) \ 
    708       emitm_fistpl((pc), emit_None, emit_None, emit_None, (m)) 
    709  
    710 #else /* INTVAL_SIZE */ 
    711  
    712 #  define jit_emit_fload_m_i(interp, pc, address) \ 
    713       emitm_fildll((interp), (pc), emit_None, emit_None, emit_None, (address)) 
    714 #  define jit_emit_fload_mb_i(interp, pc, offs) \ 
    715       emitm_fildll((interp), (pc), emit_EBX, emit_None, 1, (offs)) 
    716 #  define jit_emit_fstore_m_i(pc, m) \ 
    717       emitm_fistpll((pc), emit_None, emit_None, emit_None, (m)) 
    718  
    719 #endif /* INTVAL_SIZE */ 
    720  
    721 /* 0xD8 ops */ 
    722 #  define emitm_fadd(pc, sti) emitm_fl_3((pc), emit_b000, emit_b000, (sti)) 
    723 #  define emitm_fmul(pc, sti) emitm_fl_3((pc), emit_b000, emit_b001, (sti)) 
    724 #  define emitm_fsub(pc, sti) emitm_fl_3((pc), emit_b000, emit_b100, (sti)) 
    725 #  define emitm_fdiv(pc, sti) emitm_fl_3((pc), emit_b000, emit_b110, (sti)) 
    726  
    727 /* 0xD9 ops */ 
    728 #  define emitm_fldz(pc)  { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xee; } 
    729 #  define emitm_fld1(pc)  { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe8; } 
    730 #  define emitm_fsqrt(pc) { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfa; } 
    731 #  define emitm_fsin(pc)  { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xfe; } 
    732 #  define emitm_fcos(pc)  { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xff; } 
    733 #  define emitm_fxam(pc)  { *((pc)++) = (char) 0xd9; *((pc)++) = (char) 0xe5; } 
    734  
    735 /* FXCH ST, ST(i) , optimize 2 consecutive fxch with same reg */ 
    736 #  define emitm_fxch(pc, sti) { \ 
    737     emitm_fl_3((pc), emit_b001, emit_b001, (sti)); \ 
    738 } 
    739  
    740 /* FLD ST, ST(i), optimized FSTP(N+1);FLD(N) => FST(N+1)  */ 
    741 extern unsigned char *lastpc; 
    742 #  define emitm_fld(pc, sti) do { \ 
    743      if ((unsigned char *)(pc) == (lastpc + 2) && \ 
    744        (int)(*lastpc) == (int)0xDD && \ 
    745        (int)lastpc[1] == (int)(0xD8+(sti)+1)) \ 
    746        lastpc[1] = 0xD0+(sti)+1; \ 
    747      else \ 
    748        emitm_fl_3((pc), emit_b001, emit_b000, (sti)); \ 
    749   } while (0) 
    750  
    751 /* 0xDA, 0xDB ops */ 
    752 /* FCMOV*, FCOMI PPRO */ 
    753  
    754 /* 0xDC like 0xD8 with reversed operands */ 
    755 #  define emitm_faddr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b000, (sti)) 
    756 #  define emitm_fmulr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b001, (sti)) 
    757 #  define emitm_fsubr(pc, sti) emitm_fl_3((pc), emit_b100, emit_b100, (sti)) 
    758  
    759 /* 0xDD ops */ 
    760 /* FFree ST(i) */ 
    761 #  define emitm_ffree(pc, sti) emitm_fl_3((pc), emit_b101, emit_b000, (sti)) 
    762  
    763 /* FST ST(i) = ST */ 
    764 #  define emitm_fst(pc, sti) emitm_fl_3((pc), emit_b101, emit_b010, (sti)) 
    765  
    766 /* FSTP ST(i) = ST, POP */ 
    767 #  define emitm_fstp(pc, sti) { \ 
    768     lastpc = (unsigned char*) (pc); \ 
    769     emitm_fl_3((pc), emit_b101, emit_b011, (sti)); \ 
    770 } 
    771  
    772 /* FUCOM ST(i) <=> ST  unordered compares */ 
    773 #  define emitm_fucom(pc, sti) emitm_fl_3((pc), emit_b101, emit_b100, (sti)) 
    774  
    775 /* FUCOMP ST(i) <=> ST, POP */ 
    776 #  define emitm_fucomp(pc, sti) emitm_fl_3((pc), emit_b101, emit_b101, (sti)) 
    777  
    778 /* 0xDE ops */ 
    779 /* FADDP Add ST(i) = ST + ST(i); POP  */ 
    780 #  define emitm_faddp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b000, (sti)) 
    781  
    782 /* FMULP Mul ST(i) = ST * ST(i); POP  */ 
    783 #  define emitm_fmulp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b001, (sti)) 
    784  
    785 /* FSUB ST = ST - ST(i) */ 
    786  
    787 /* FSUBRP SubR ST(i) = ST - ST(i); POP  */ 
    788 #  define emitm_fsubrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b100, (sti)) 
    789  
    790 /* FSUBP Sub ST(i) = ST(i) - ST; POP  */ 
    791 #  define emitm_fsubp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b101, (sti)) 
    792  
    793 /* FDIVRP DivR ST(i) = ST(i) / ST(0); POP  */ 
    794 #  define emitm_fdivrp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b110, (sti)) 
    795  
    796 /* FDIVP Div ST(i) = ST(0) / ST(i); POP ST(0) */ 
    797 #  define emitm_fdivp(pc, sti) emitm_fl_3((pc), emit_b110, emit_b111, (sti)) 
    798  
    799 /* 0xDF OPS: FCOMIP, FUCOMIP PPRO */ 
    800  
    801 /* Negate - called change sign */ 
    802 #  define emitm_fchs(pc) emitm_fl_4((pc), 0) 
    803  
    804 /* ABS - ST(0) = ABS(ST(0)) */ 
    805 #  define emitm_fabs(pc) emitm_fl_4((pc), 1) 
    806  
    807 /* Comparisons */ 
    808  
    809 #  define emitm_fcom(pc, sti) emitm_fl_3((pc), emit_b000, emit_b010, (sti)) 
    810  
    811 #  define emitm_fcomp(pc, sti) emitm_fl_3((pc), emit_b000, emit_b011, (sti)) 
    812  
    813 #ifdef PARROT_HAS_JIT_FCOMIP 
    814 #  define emitm_fcomip(pc, sti) emitm_fl_3((pc), emit_b111, emit_b110, (sti)) 
    815 #  define emitm_fcomi(pc, sti) emitm_fl_3((pc), emit_b011, emit_b110, (sti)) 
    816 #else 
    817 #  define emitm_fcomip(pc, sti) do { \ 
    818       emitm_fcomp((pc), (sti)); \ 
    819       emitm_fstw(pc); \ 
    820       emitm_sahf(pc); \ 
    821     } while (0) 
    822 #  define emitm_fcomi(pc, sti) do { \ 
    823       emitm_fcom((pc), (sti)); \ 
    824       emitm_fstw(pc); \ 
    825       emitm_sahf(pc); \ 
    826     } while (0) 
    827 #endif 
    828  
    829 #  define emitm_fcompp(pc) { *((pc)++) = (char) 0xde; *((pc)++) = (char) 0xd9; } 
    830  
    831 #  define emitm_fcom_m(interp, pc, b, i, s, d) \ 
    832     emitm_fl_2((interp), (pc), emit_b10, 0, emit_b010, (b), (i), (s), (d)) 
    833  
    834 #  define emitm_fcomp_m(interp, pc, b, i, s, d) \ 
    835     emitm_fl_2((interp), (pc), emit_b10, 0, emit_b011, (b), (i), (s), (d)) 
    836  
    837 /* ST -= real64 */ 
    838 #  define emitm_fsub_m(interp, pc, b, i, s, d) \ 
    839     emitm_fl_2((interp), (pc), emit_b10, 0, emit_b100, (b), (i), (s), (d)) 
    840  
    841 /* ST -= int32_mem */ 
    842 #  define emitm_fisub_m(interp, pc, b, i, s, d) \ 
    843     emitm_fl_2((interp), (pc), emit_b01, 0, emit_b100, (b), (i), (s), (d)) 
    844  
    845 #  define emitm_fadd_m(interp, pc, b, i, s, d) \ 
    846     emitm_fl_2((interp), (pc), emit_b10, 0, emit_b000, (b), (i), (s), (d)) 
    847  
    848 /* ST += int32_mem */ 
    849 #  define emitm_fiadd_m(interp, pc, b, i, s, d) \ 
    850     emitm_fl_2((interp), (pc), emit_b01, 0, emit_b000, (b), (i), (s), (d)) 
    851  
    852 /* ST *= real64 */ 
    853 #  define emitm_fmul_m(interp, pc, b, i, s, d) \ 
    854     emitm_fl_2((interp), (pc), emit_b10, 0, emit_b001, (b), (i), (s), (d)) 
    855  
    856 /* ST *= int32_mem */ 
    857 #  define emitm_fimul_m(interp, pc, b, i, s, d) \ 
    858     emitm_fl_2((interp), (pc), emit_b01, 0, emit_b001, (b), (i), (s), (d)) 
    859  
    860 /* ST /= real64 */ 
    861 #  define emitm_fdiv_m(interp, pc, b, i, s, d) \ 
    862     emitm_fl_2((interp), (pc), emit_b10, 0, emit_b110, (b), (i), (s), (d)) 
    863  
    864 /* ST /= int32_mem */ 
    865 #  define emitm_fidiv_m(interp, pc, b, i, s, d) \ 
    866     emitm_fl_2((interp), (pc), emit_b01, 0, emit_b110, (b), (i), (s), (d)) 
    867  
    868 /* Ops Needed to support loading EFLAGs for conditional branches */ 
    869 #  define emitm_fstw(pc) emitm_fl_3((pc), emit_b111, emit_b100, emit_b000) 
    870  
    871 #  define emitm_sahf(pc) *((pc)++) = (char) 0x9e 
    872  
    873 /* misc float */ 
    874 #  define emitm_ftst(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xE4; } 
    875 #  define emitm_fprem(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF8; } 
    876 #  define emitm_fprem1(pc) { *(pc)++ = 0xd9; *(pc)++ = 0xF5; } 
    877  
    878 #  define emitm_fldcw(interp, pc, mem) \ 
    879     emitm_fl_2((interp), (pc), emit_b00, 1, emit_b101, 0, 0, 0, (mem)) 
    880  
    881 #if defined(NEG_MINUS_ZERO) 
    882 #  define jit_emit_neg_r_n(pc, r) { \ 
    883        if (r) { \ 
    884          emitm_fld((pc), (r)); \ 
    885        } \ 
    886        emitm_fchs(pc); \ 
    887        if (r) { \ 
    888          emitm_fstp((pc), ((r)+1)); \ 
    889        } \ 
    890      } 
    891  
    892 #  define jit_emit_neg_M_n(interp, pc, mem) { \ 
    893        jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \ 
    894        emitm_fchs(pc); \ 
    895        jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \ 
    896      } 
    897  
    898 #elif defined(NEG_ZERO_SUB) 
    899  
    900 #  define jit_emit_neg_r_n(pc, r) { \ 
    901        emitm_fldz(pc); \ 
    902        emitm_fsubrp((pc), ((r)+1)); \ 
    903      } 
    904  
    905 #  define jit_emit_neg_M_n(interp, pc, mem) { \ 
    906        jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \ 
    907        emitm_fldz(pc); \ 
    908        emitm_fsubrp((pc), 1); \ 
    909        jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \ 
    910      } 
    911 #else 
    912  
    913 #  define jit_emit_neg_r_n(pc, r) { \ 
    914        if (r) { \ 
    915          emitm_fld((pc), (r)); \ 
    916        } \ 
    917        emitm_ftst(pc); \ 
    918        emitm_fstw(pc); \ 
    919        emitm_sahf(pc); \ 
    920        emitm_jxs((pc), emitm_jz, 2); \ 
    921        emitm_fchs(pc); \ 
    922        if (r) { \ 
    923          emitm_fstp((pc), ((r)+1)); \ 
    924        } \ 
    925      } 
    926  
    927 #  define jit_emit_neg_M_n(interp, pc, mem) { \ 
    928        jit_emit_fload_mb_n((interp), (pc), emit_EBX, (mem)); \ 
    929        emitm_ftst(pc); \ 
    930        emitm_fstw(pc); \ 
    931        emitm_sahf(pc); \ 
    932        emitm_jxs((pc), emitm_jz, 2); \ 
    933        emitm_fchs(pc); \ 
    934        jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (mem)); \ 
    935      } 
    936 #endif 
    937  
    938 #  define jit_emit_sin_r_n(pc, r) \ 
    939      if (r) { \ 
    940        emitm_fld((pc), (r)); \ 
    941      } \ 
    942      emitm_fsin(pc); \ 
    943      if (r) { \ 
    944        emitm_fstp((pc), ((r)+1)); \ 
    945      } 
    946  
    947 #  define jit_emit_cos_r_n(pc, r) \ 
    948      if (r) { \ 
    949        emitm_fld((pc), (r)); \ 
    950      } \ 
    951      emitm_fcos(pc); \ 
    952      if (r) { \ 
    953        emitm_fstp((pc), ((r)+1)); \ 
    954      } 
    955  
    956 #  define jit_emit_sqrt_r_n(pc, r) \ 
    957      if (r) { \ 
    958        emitm_fld((pc), (r)); \ 
    959      } \ 
    960      emitm_fsqrt(pc); \ 
    961      if (r) { \ 
    962        emitm_fstp((pc), ((r)+1)); \ 
    963      } 
    964  
    965 #  define jit_emit_abs_r_n(pc, r) { \ 
    966      if (r) { \ 
    967        emitm_fld((pc), (r)); \ 
    968      } \ 
    969      emitm_fabs(pc); \ 
    970      if (r) { \ 
    971        emitm_fstp((pc), ((r)+1)); \ 
    972      } \ 
    973    } 
    974  
    975 #  define jit_emit_abs_r_i(pc, r) { \ 
    976      jit_emit_test_r_i((pc), (r)); \ 
    977      emitm_jxs((pc), emitm_jns, 3); \ 
    978      jit_emit_not_r_i((pc), (r)); \ 
    979      jit_emit_inc_r_i((pc), (r)); \ 
    980    } 
    981  
    982 #  define jit_emit_abs_m_n(interp, pc, mem) { \ 
    983      jit_emit_fload_m_n((interp), (pc), (mem)); \ 
    984      emitm_fabs(pc); \ 
    985      jit_emit_fstore_m_n((pc), (mem)); \ 
    986    } 
    987  
    988 /* Integer comparisons */ 
    989 #  define jit_emit_cmp_rr(pc, reg1, reg2) \ 
    990     emitm_alul_r_r((pc), 0x39, (reg2), (reg1)) 
    991 #  define jit_emit_cmp_rr_i(pc, r1, r2) jit_emit_cmp_rr((pc), (r1), (r2)) 
    992  
    993 #  define emitm_cmpl_r_m(pc, reg, b, i, s, d) \ 
    994     emitm_alul_r_m((pc), 0x3b, (reg), (b), (i), (s), (d)) 
    995  
    996 #  define emitm_cmpl_m_r(pc, reg, b, i, s, d) \ 
    997     emitm_alul_r_m((pc), 0x39, (reg), (b), (i), (s), (d)) 
    998  
    999 #  define jit_emit_cmp_ri_i(interp, pc, reg, imm) \ 
    1000     emitm_alul_i_r((pc), 0x81, emit_b111, (imm), (reg)) 
    1001  
    1002 /* Unconditional Jump/Call */ 
    1003  
    1004 #  define emitm_call_cfunc(pc, func) emitm_calll((pc), (char *)(func) - (pc) - 4) 
    1005  
    1006 #  define emitm_calll(pc, disp) { \ 
    1007     *((pc)++) = (char) 0xe8; \ 
    1008     *(long *)(pc) = (disp); (pc) += 4; } 
    1009  
    1010 #  define emitm_callr(pc, reg) { \ 
    1011     *((pc)++) = (char) 0xff; \ 
    1012     *((pc)++) = (char) 0xd0 | ((reg) - 1); } 
    1013  
    1014 #  define emitm_callm(pc, b, i, s, d) { \ 
    1015        *((pc)++) = (char) 0xff; \ 
    1016        (pc) = emit_r_X((interp), (pc), emit_reg(emit_b010), (b), (i), (s), (d)); } 
    1017  
    1018 #  define emitm_jumps(pc, disp) { \ 
    1019     *((pc)++) = (char) 0xeb; \ 
    1020     *((pc)++) = (disp); } 
    1021  
    1022 #  define emitm_jumpl(pc, disp) { \ 
    1023     *((pc)++) = (char) 0xe9; \ 
    1024     *(long *)(pc) = (disp); (pc) += 4; } 
    1025  
    1026 #  define emitm_jumpr(pc, reg) { \ 
    1027     *((pc)++) = (char) 0xff; \ 
    1028     *((pc)++) = (char)(0xe0 | ((reg) - 1)); } 
    1029  
    1030 #  define emitm_jumpm(pc, b, i, s, d) { \ 
    1031        *((pc)++) = (char) 0xff; \ 
    1032        (pc) = emit_r_X((interp), (pc), emit_reg(emit_b100), (b), (i), (s), (d)); } 
    1033  
    1034 /* Conditional jumps */ 
    1035  
    1036 /* Short jump - 8 bit disp */ 
    1037 #  define emitm_jxs(pc, code, disp) { \ 
    1038     *((pc)++) = (char)(0x70 | (code)); \ 
    1039     *((pc)++) = (char)(disp); } 
    1040  
    1041 /* Long jump - 32 bit disp */ 
    1042 #  define emitm_jxl(pc, code, disp) { \ 
    1043     *((pc)++) = (char) 0x0f; \ 
    1044     *((pc)++) = (char)(0x80 | (code));  \ 
    1045     *(long *)(pc) = (disp); (pc) += 4; } 
    1046  
    1047 #  define emitm_jo   0 
    1048 #  define emitm_jno  1 
    1049 #  define emitm_jb   2 
    1050 #  define emitm_jnb  3 
    1051 #  define emitm_jz   4 
    1052 #  define emitm_je emitm_jz 
    1053 #  define emitm_jnz  5 
    1054 #  define emitm_jne emitm_jnz 
    1055 #  define emitm_jbe  6 
    1056 #  define emitm_ja   7 
    1057 #  define emitm_js   8 
    1058 #  define emitm_jns  9 
    1059 #  define emitm_jp  10 
    1060 #  define emitm_jnp 11 
    1061 #  define emitm_jl  12 
    1062 #  define emitm_jnl 13 
    1063 #  define emitm_jle 14 
    1064 #  define emitm_jg  15 
    1065  
    1066 /* set byte conditional */ 
    1067 #  define jit_emit_setcc_r(pc, cc, r) \ 
    1068     *(pc)++ = 0x0f; \ 
    1069     *(pc)++ = 0x90 + (cc); \ 
    1070     *(pc)++ = (char) emit_alu_X_r(0, (r)) 
    1071  
    107276/* 
    1073  * core.jit interface 
    1074  * 
    1075  * The new offset based versions have uppercase RM or MR inside 
    1076  * That's probably only during transition time 
    1077  */ 
    1078  
    1079 #  define jit_emit_mov_mi_i(pc, dest, immediate) \ 
    1080     emitm_movl_i_m((pc), (immediate), emit_None, emit_None, emit_None, (dest)) 
    1081  
    1082 #  define jit_emit_mov_MI_i(interp, pc, offs, immediate) \ 
    1083     emitm_movl_i_m((pc), (immediate), emit_EBX, emit_None, 1, (offs)) 
    1084  
    1085 #  define jit_emit_mov_rm_i(interp, pc, reg, address) \ 
    1086     emitm_movl_m_r((interp), (pc), (reg), emit_None, emit_None, emit_None, (address)) 
    1087  
    1088 #  define jit_emit_mov_RM_i(interp, pc, reg, offs) \ 
    1089     emitm_movl_m_r((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1090  
    1091 #  define jit_emit_mov_mr_i(interp, pc, address, reg) \ 
    1092     emitm_movl_r_m((interp), (pc), (reg), emit_None, emit_None, emit_None, (address)) 
    1093  
    1094 #  define jit_emit_mov_MR_i(interp, pc, offs, reg) \ 
    1095     emitm_movl_r_m((interp), (pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1096  
    1097 #  define jit_emit_mul_RM_i(interp, pc, reg, offs) \ 
    1098     emitm_smull_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1099  
    1100 #  define jit_emit_sub_RM_i(interp, pc, reg, offs) \ 
    1101     emitm_subl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1102  
    1103 #  define jit_emit_sub_MR_i(interp, pc, offs, reg) \ 
    1104     emitm_subl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1105  
    1106 #  define jit_emit_sub_MI_i(pc, offs, imm) \ 
    1107     emitm_subl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs)) 
    1108  
    1109 #  define jit_emit_add_RM_i(interp, pc, reg, offs) \ 
    1110     emitm_addl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1111  
    1112 #  define jit_emit_add_MR_i(interp, pc, offs, reg) \ 
    1113     emitm_addl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1114  
    1115 #  define jit_emit_add_MI_i(pc, offs, imm) \ 
    1116     emitm_addl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs)) 
    1117  
    1118 #  define jit_emit_cmp_rm_i(pc, reg, address) \ 
    1119     emitm_cmpl_r_m((pc), (reg), emit_None, emit_None, emit_None, (address)) 
    1120  
    1121 #  define jit_emit_cmp_RM_i(interp, pc, reg, offs) \ 
    1122     emitm_cmpl_r_m((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1123  
    1124 #  define jit_emit_cmp_MR_i(interp, pc, offs, reg) \ 
    1125     emitm_cmpl_m_r((pc), (reg), emit_EBX, emit_None, 1, (offs)) 
    1126  
    1127 /* high level routines, behave like real 2 register FP */ 
    1128  
    1129 /* mapped float registers numbers are ST(1)-ST(4). 
    1130  * scratch register is ST(0) 
    1131  */ 
    1132  
    1133 /* ST(i) <- numvar */ 
    1134 #  define jit_emit_mov_RM_n(interp, pc, r, d) { \ 
    1135     jit_emit_fload_mb_n((interp), (pc), emit_EBX, (d)); \ 
    1136     emitm_fstp((pc), ((r)+1)); \ 
    1137 } 
    1138  
    1139 /* ST(i) <= NUM_CONST */ 
    1140 #  define jit_emit_mov_ri_n(interp, pc, r, i) { \ 
    1141     jit_emit_fload_m_n((interp), (pc), (i)); \ 
    1142     emitm_fstp((pc), ((r)+1)); \ 
    1143 } 
    1144  
    1145 /* ST(i) <= &INT_CONST */ 
    1146 #  define jit_emit_mov_ri_ni(interp, pc, r, i) { \ 
    1147     jit_emit_fload_m_i((interp), (pc), (i)); \ 
    1148     emitm_fstp((pc), ((r)+1)); \ 
    1149 } 
    1150  
    1151 /* ST(i) <= INT_REG */ 
    1152 #  define jit_emit_mov_RM_ni(interp, pc, r, i) { \ 
    1153     jit_emit_fload_mb_i((interp), (pc), (i)); \ 
    1154     emitm_fstp((pc), ((r)+1)); \ 
    1155 } 
    1156  
    1157 /* NUM_REG(i) <= &INT_CONST 
    1158  * the int const i is loaded from the code memory 
    1159  */ 
    1160 #  define jit_emit_mov_MI_ni(interp, pc, offs, i) { \ 
    1161     jit_emit_fload_m_i((interp), (pc), (i)); \ 
    1162     jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \ 
    1163 } 
    1164  
    1165 /* INT_REG <= ST(i) */ 
    1166 #  define jit_emit_mov_mr_in(pc, mem, r) { \ 
    1167     emitm_fld((pc), (r)); \ 
    1168     jit_emit_fstore_m_i((pc), (mem)); \ 
    1169 } 
    1170  
    1171 /* numvar <- ST(i) */ 
    1172 #  define jit_emit_mov_mr_n(pc, d, r) { \ 
    1173     emitm_fld((pc), (r)); \ 
    1174     jit_emit_fstore_m_n((pc), (d)); \ 
    1175 } 
    1176  
    1177 #  define jit_emit_mov_MR_n(interp, pc, d, r) { \ 
    1178     if (r) { \ 
    1179         emitm_fld((pc), (r)); \ 
    1180         jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (d)); \ 
    1181     } \ 
    1182     else { \ 
    1183         jit_emit_fst_mb_n((interp), (pc), emit_EBX, (d)); \ 
    1184     } \ 
    1185 } 
    1186  
    1187 /* ST(r1) <= ST(r2) */ 
    1188 #  define jit_emit_mov_rr_n(pc, r1, r2) { \ 
    1189     if ((r1) != (r2)) { \ 
    1190       if (r2) { \ 
    1191         emitm_fld((pc), (r2)); \ 
    1192         emitm_fstp((pc), ((r1)+1)); \ 
    1193       } \ 
    1194       else { \ 
    1195         emitm_fst((pc), (r1)); \ 
    1196       } \ 
    1197     } \ 
    1198 } 
    1199  
    1200 /* ST(r1) xchg ST(r2) */ 
    1201 #  define jit_emit_xchg_rr_n(interp, pc, r1, r2) { \ 
    1202     if ((r1) != (r2)) { \ 
    1203       emitm_fld((pc), (r1)); \ 
    1204       emitm_fld((pc), ((r2)+1)); \ 
    1205       emitm_fstp((pc), ((r1)+2)); \ 
    1206       emitm_fstp((pc), ((r2)+1)); \ 
    1207     } \ 
    1208 } 
    1209  
    1210 #  define jit_emit_xchg_RM_n(interp, pc, r, offs) { \ 
    1211     emitm_fld((pc), (r)); \ 
    1212     jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \ 
    1213     emitm_fstp((pc), ((r)+2)); \ 
    1214     jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \ 
    1215 } 
    1216  
    1217 #  define jit_emit_xchg_MR_n(interp, pc, offs, r) { \ 
    1218     emitm_fld((pc), (r)); \ 
    1219     jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \ 
    1220     emitm_fstp((pc), ((r)+2)); \ 
    1221     jit_emit_fstore_mb_n((interp), (pc), emit_EBX, (offs)); \ 
    1222 } 
    1223  
    1224 #  define jit_emit_finit(pc) { *((pc)++) = (char) 0xdb; *((pc)++) = (char) 0xe3; } 
    1225  
    1226 /* ST(i) op= MEM */ 
    1227  
    1228 #  define jit_emit_xxx_rm_n(interp, op, pc, r, m) { \ 
    1229     jit_emit_fload_m_n((interp), (pc), (m)); \ 
    1230     emitm_f ## op ## p((pc), ((r)+1)); \ 
    1231 } 
    1232  
    1233 #  define jit_emit_xxx_RM_n(interp, op, pc, r, offs) { \ 
    1234     jit_emit_fload_mb_n((interp), (pc), emit_EBX, (offs)); \ 
    1235     emitm_f ## op ## p((pc), ((r)+1)); \ 
    1236 } 
    1237  
    1238 /* 
    1239  * float ops in two flavors: abs memory for constants, offsets for regs 
    1240  */ 
    1241  
    1242 #  define jit_emit_add_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), add, (pc), (r), (m)) 
    1243 #  define jit_emit_sub_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), sub, (pc), (r), (m)) 
    1244 #  define jit_emit_mul_ri_n(interp, pc, r, m) jit_emit_xxx_rm_n((interp), mul, (pc), (r), (m)) 
    1245  
    1246 #  define jit_emit_add_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), add, (pc), (r), (o)) 
    1247 #  define jit_emit_sub_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), sub, (pc), (r), (o)) 
    1248 #  define jit_emit_mul_RM_n(interp, pc, r, o) jit_emit_xxx_RM_n((interp), mul, (pc), (r), (o)) 
    1249  
    1250 /* ST(r1) += ST(r2) */ 
    1251 /* r1 == 0:  ST(0) <- ST(0) + ST(i) 
    1252  * r2 == 0:  ST(i) <- ST(0) + ST(i) 
    1253  */ 
    1254 #  define jit_emit_add_rr_n(interp, pc, r1, r2) do { \ 
    1255         if (!(r1)) { \ 
    1256           emitm_fadd((pc), (r2)); \ 
    1257         }  \ 
    1258         else if (!(r2)) { \ 
    1259           emitm_faddr((pc), (r1)); \ 
    1260         }  \ 
    1261         else { \ 
    1262             emitm_fld((pc), (r2)); \ 
    1263             emitm_faddp((pc), ((r1)+1)); \ 
    1264         } \ 
    1265     } \ 
    1266     while (0) 
    1267 /* 
    1268  * ST(r) += INT_REG 
    1269  */ 
    1270 #  define jit_emit_add_RM_ni(pc, r, offs) { \ 
    1271     emitm_fld((pc), (r)); \ 
    1272     emitm_fiadd_m((pc), emit_EBX, 0, 1, (offs)); \ 
    1273     emitm_fstp((pc), ((r)+1)); \ 
    1274 } 
    1275  
    1276 /* ST(r1) -= ST(r2) */ 
    1277 /* r1 == 0:  ST(0) <- ST(0) - ST(i) 
    1278  * r2 == 0:  ST(i) <- ST(i) - ST(0) 
    1279  */ 
    1280 #  define jit_emit_sub_rr_n(interp, pc, r1, r2) do { \ 
    1281         if (!(r1)) { \ 
    1282           emitm_fsub((pc), (r2)); \ 
    1283         }  \ 
    1284         else if (!(r2)) { \ 
    1285           emitm_fsubr((pc), (r1)); \ 
    1286         }  \ 
    1287         else { \ 
    1288             emitm_fld((pc), (r2)); \ 
    1289             emitm_fsubp((pc), ((r1)+1)); \ 
    1290         } \ 
    1291     } \ 
    1292     while (0) 
    1293  
    1294 /* 
    1295  * ST(r) -= INT_REG 
    1296  */ 
    1297 #  define jit_emit_sub_RM_ni(pc, r, offs) { \ 
    1298     emitm_fld((pc), (r)); \ 
    1299     emitm_fisub_m((pc), emit_EBX, 0, 1, (offs)); \ 
    1300     emitm_fstp((pc), ((r)+1)); \ 
    1301 } 
    1302  
    1303 #  define jit_emit_inc_r_n(pc, r) { \ 
    1304     emitm_fld1(pc); \ 
    1305     emitm_faddp((pc), ((r)+1)); \ 
    1306 } 
    1307  
    1308 #  define jit_emit_dec_r_n(pc, r) { \ 
    1309     emitm_fld1(pc); \ 
    1310     emitm_fsubp((pc), ((r)+1)); \ 
    1311 } 
    1312  
    1313 /* ST(r1) *= ST(r2) */ 
    1314 /* r1 == 0:  ST(0) <- ST(0) * ST(i) 
    1315  * r2 == 0:  ST(i) <- ST(0) * ST(i) 
    1316  */ 
    1317 #  define jit_emit_mul_rr_n(interp, pc, r1, r2) do { \ 
    1318         if (!(r1)) { \ 
    1319           emitm_fmul((pc), (r2)); \ 
    1320         }  \ 
    1321         else if (!(r2)) { \ 
    1322           emitm_fmulr((pc), (r1)); \ 
    1323         }  \ 
    1324         else { \ 
    1325             emitm_fld((pc), (r2)); \ 
    1326             emitm_fmulp((pc), ((r1)+1)); \ 
    1327         } \ 
    1328     } \ 
    1329     while (0) 
    1330  
    1331 /* 
    1332  * ST(r) *= INT_REG 
    1333  */ 
    1334 #  define jit_emit_mul_RM_ni(pc, r, offs) { \ 
    1335     emitm_fld((pc), (r)); \ 
    1336     emitm_fimul_m((pc), emit_EBX, 0, 1, (offs)); \ 
    1337     emitm_fstp((pc), ((r)+1)); \ 
    1338 } 
    1339  
    1340 /* 
    1341  * ST(r) /= INT_REG 
    1342  */ 
    1343 #  define jit_emit_div_RM_ni(pc, r, offs) { \ 
    1344     emitm_fld((pc), (r)); \ 
    1345     emitm_fidiv_m((pc), emit_EBX, 0, 1, (offs)); \ 
    1346     emitm_fstp((pc), ((r)+1)); \ 
    1347 } 
    1348  
    1349 /* test r for zero */ 
    1350 #  define jit_emit_test_r_n(pc, r) { \ 
    1351     if (r) { \ 
    1352       emitm_fxch((pc), (r)); \ 
    1353     } \ 
    1354     emitm_fxam(pc); \ 
    1355     emitm_fstw(pc); \ 
    1356     emitm_sahf(pc); \ 
    1357     if (r) { \ 
    1358       emitm_fxch((pc), (r)); \ 
    1359     } \ 
    1360 } 
    1361  
    1362 enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL }; 
    1363  
    1364 #  define jit_emit_stack_frame_enter(pc) do { \ 
    1365     emitm_pushl_r((pc), emit_EBP); \ 
    1366     jit_emit_mov_rr_i((pc), emit_EBP, emit_ESP); \ 
    1367 } while (0) 
    1368  
    1369 #  define jit_emit_stack_frame_leave(pc) do { \ 
    1370     jit_emit_mov_rr_i((pc), emit_ESP, emit_EBP); \ 
    1371     emitm_popl_r((pc), emit_EBP); \ 
    1372 } while (0) 
    1373  
    1374 #  define jit_emit_end(pc) { \ 
    1375        jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \ 
    1376        emitm_popl_r((pc), emit_EDI); \ 
    1377        emitm_popl_r((pc), emit_ESI); \ 
    1378        emitm_popl_r((pc), emit_EBX); \ 
    1379        emitm_popl_r((pc), emit_EBP); \ 
    1380        emitm_ret(pc); \ 
    1381      } 
    1382  
    1383 size_t calc_signature_needs(const char *sig, int *strings); 
    1384  
    1385 void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, 
    1386     STRING *signature, int *sizeptr); 
    1387  
    1388 /* 
    1389  * register usage 
    1390  * %edi, %esi ... mapped, preserved 
    1391  * %edx, %ecx ... mapped, not preserved 
    1392  * %ebx       ... base pointer for register access, preserved 
    1393  * %eax       ... scratch, return value register 
    1394  */ 
    1395  
    1396 #endif /* PARROT_I386_JIT_EMIT_H_GUARD */ 
    1397  
    1398 /* 
    139977 * Local variables: 
    140078 *   c-file-style: "parrot" 
    140179 * End: 
  • src/nci_test.c

     
    109109PARROT_EXPORT void   nci_vfff(float, float, float); 
    110110PARROT_EXPORT void   nci_vV(const char **); 
    111111PARROT_EXPORT void   nci_vVVV(const char **, const char **, const char **); 
     112PARROT_EXPORT int    nci_i20(int, int, int, int, int, int, int, int, int, int, int, int, int, int, 
     113                             int, int, int, int, int); 
    112114 
    113115/* Declarations for callback tests */ 
    114116 
     
    11901192  *ptr3 = "Go suck a lemon.\n"; 
    11911193} 
    11921194 
     1195/* 
     1196 
     1197=item C<int 
     1198nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10, 
     1199        int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18)> 
     1200 
     1201Prints and returns the nth value in a list of integers. First argument is the selector; subsequents, 
     1202the list. 
     1203 
     1204This function is designed to be outside of the range of the static frame builder as an excercise for 
     1205the dynamic frame builder. 
     1206 
     1207=cut 
     1208 
     1209*/ 
     1210PARROT_EXPORT int 
     1211nci_i20(int sel, int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9, int v10, 
     1212        int v11, int v12, int v13, int v14, int v15, int v16, int v17, int v18) { 
     1213    int *selected; 
     1214    switch ((sel < 0 ? -sel : sel) % 18) { 
     1215        case 0: selected = &v1; break; 
     1216        case 1: selected = &v2; break; 
     1217        case 2: selected = &v3; break; 
     1218        case 3: selected = &v4; break; 
     1219        case 4: selected = &v5; break; 
     1220        case 5: selected = &v6; break; 
     1221        case 6: selected = &v7; break; 
     1222        case 7: selected = &v8; break; 
     1223        case 8: selected = &v9; break; 
     1224        case 9: selected = &v10; break; 
     1225        case 10: selected = &v11; break; 
     1226        case 11: selected = &v12; break; 
     1227        case 12: selected = &v13; break; 
     1228        case 13: selected = &v14; break; 
     1229        case 14: selected = &v15; break; 
     1230        case 15: selected = &v16; break; 
     1231        case 16: selected = &v17; break; 
     1232        case 17: selected = &v18; break; 
     1233        default: printf("default case reached (should never happen)"); return -1; 
     1234    } 
     1235    printf("%d\n", *selected); 
     1236    return *selected; 
     1237} 
     1238 
    11931239#ifdef TEST 
    11941240 
    11951241char l2 = 4; 
  • tools/build/nativecall.pl

     
    467467        return F2DPTR(VTABLE_get_pointer(interp, b)); 
    468468    } 
    469469    else { 
    470         int jit_size; 
    471         void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &jit_size); 
     470        void *priv; 
     471        void * const result = Parrot_jit_build_call_func(interp, pmc_nci, signature, &priv); 
    472472        if (result) { 
    473             struct jit_buffer_private_data *priv; 
    474473            *jitted = 1; 
    475474            temp_pmc = pmc_new(interp, enum_class_ManagedStruct); 
    476475            VTABLE_set_pointer(interp, temp_pmc, (void *)result); 
    477476#ifdef PARROT_HAS_EXEC_PROTECT 
    478             priv = (struct jit_buffer_private_data *) 
    479                 mem_sys_allocate(sizeof(struct jit_buffer_private_data)); 
    480             priv->size = jit_size; 
    481477            SETATTR_ManagedStruct_custom_free_func(interp, temp_pmc, Parrot_jit_free_buffer); 
    482478            SETATTR_ManagedStruct_custom_free_priv(interp, temp_pmc, priv); 
    483479            SETATTR_ManagedStruct_custom_clone_func(interp, temp_pmc, Parrot_jit_clone_buffer); 
  • lib/Parrot/Configure/Options/Conf.pm

     
    105105   --without-gmp        Build parrot without GMP support 
    106106   --without-opengl     Build parrot without OpenGL support (GL/GLU/GLUT) 
    107107   --without-pcre       Build parrot without pcre support 
     108   --without-libjit     Build parrot without LibJIT support 
    108109 
    109110ICU Options: 
    110111 
  • lib/Parrot/Configure/Options/Conf/Shared.pm

     
    7575    without-gettext 
    7676    without-gmp 
    7777    without-icu 
     78    without-libjit 
    7879    without-opengl 
    7980    without-pcre 
    8081    without-threads 
  • lib/Parrot/Configure/Step/List.pm

     
    6464    auto::ctags 
    6565    auto::revision 
    6666    auto::icu 
     67    auto::libjit 
    6768    gen::config_h 
    6869    gen::core_pmcs 
    6970    gen::crypto 
     
    7374    gen::makefiles 
    7475    gen::platform 
    7576    gen::config_pm 
     77    gen::libjit 
    7678); 
    7779 
    7880sub get_steps_list { return @steps; } 
  • t/pmc/nci.t

     
    66use warnings; 
    77use lib qw( . lib ../lib ../../lib ); 
    88use Test::More; 
    9 use Parrot::Test tests => 70; 
     9use Parrot::Test tests => 71; 
    1010use Parrot::Config qw(%PConfig); 
    1111 
    1212=head1 NAME 
     
    27532753Go suck a lemon. 
    27542754OUTPUT 
    27552755 
     2756my $test_code = <<'CODE'; 
     2757.sub test :main 
     2758    .local pmc libnci_test 
     2759    $S0 = 'libnci_test' 
     2760    libnci_test = loadlib $S0 
     2761 
     2762    .local pmc nci_i20 
     2763    nci_i20 = dlfunc libnci_test, "nci_i20", "iiiiiiiiiiiiiiiiiiii" 
     2764 
     2765    .local pmc args 
     2766    args = new ['FixedIntegerArray'] 
     2767    args = 18 
     2768 
     2769    $I0 = 2 
     2770    args[0] = 1 
     2771    args[1] = 1 
     2772 
     2773LOOP1: 
     2774    $I1 = $I0 - 1 
     2775    $I1 = args[$I1] 
     2776 
     2777    $I2 = $I0 - 2 
     2778    $I2 = args[$I2] 
     2779 
     2780    $I3 = $I1 + $I2 
     2781    args[$I0] = $I3 
     2782    inc $I0 
     2783    if $I0 < 18 goto LOOP1 
     2784 
     2785    $I0 = args 
     2786    dec $I0 
     2787 
     2788    $I1 = args[0] 
     2789    $I2 = args[1] 
     2790    $I3 = args[2] 
     2791    $I4 = args[3] 
     2792    $I5 = args[4] 
     2793    $I6 = args[5] 
     2794    $I7 = args[6] 
     2795    $I8 = args[7] 
     2796    $I9 = args[8] 
     2797    $I10 = args[9] 
     2798    $I11 = args[10] 
     2799    $I12 = args[11] 
     2800    $I13 = args[12] 
     2801    $I14 = args[13] 
     2802    $I15 = args[14] 
     2803    $I16 = args[15] 
     2804    $I17 = args[16] 
     2805    $I18 = args[17] 
     2806 
     2807LOOP2: 
     2808    nci_i20($I0, $I1, $I2, $I3, $I4, $I5, $I6, $I7, $I8, $I9, $I10, $I11, $I12, $I13, $I14, $I15, $I16, $I17, $I18) 
     2809    $I0 = $I0 / 2 
     2810    if $I0 > 0 goto LOOP2 
     2811.end 
     2812CODE 
     2813if ($PConfig{cc_build_call_frames}) { 
     2814    pir_output_is($test_code, <<DYNAMIC_FRAMEBUILDER_OUTPUT, 'dynamic frame builder builds ridiculous call frames'); 
     28152584 
     281634 
     28175 
     28182 
     28191 
     2820DYNAMIC_FRAMEBUILDER_OUTPUT 
     2821} else { 
     2822    my $output_re = qr/^Parrot VM: PANIC: iiiiiiiiiiiiiiiiiiii is an unknown signature type./; 
     2823    pir_error_output_like($test_code, $output_re, "static frame builder can't build ridiculous signatures"); 
     2824} 
     2825 
    27562826# Local Variables: 
    27572827#   mode: cperl 
    27582828#   cperl-indent-level: 4 
  • t/steps/auto/libjit-01.t

     
     1#! perl 
     2# Copyright (C) 2009, Parrot Foundation. 
     3# $Id$ 
     4# auto/libjit-01.t 
     5 
     6use strict; 
     7use warnings; 
     8 
     9use Test::More tests => 9; 
     10 
     11use lib 'lib'; 
     12 
     13use Parrot::Configure; 
     14use Parrot::Configure::Options 'process_options'; 
     15use Parrot::Configure::Test qw( 
     16    test_step_thru_runstep 
     17    test_step_constructor_and_description 
     18); 
     19 
     20use_ok('config::init::defaults'); 
     21use_ok('config::auto::libjit'); 
     22 
     23########## _select_lib() ########## 
     24 
     25my ($args, $step_list_ref) = process_options( 
     26    { 
     27        argv => [], 
     28        mode => 'configure', 
     29    } 
     30); 
     31 
     32my $conf = Parrot::Configure->new; 
     33 
     34test_step_thru_runstep( $conf, 'init::defaults', $args ); 
     35 
     36my $pkg = 'auto::libjit'; 
     37 
     38$conf->add_steps($pkg); 
     39$conf->options->set(%$args); 
     40my $stp = test_step_constructor_and_description($conf); 
     41 
     42################### DOCUMENTATION ################### 
     43 
     44=head1 NAME 
     45 
     46auto/libjit-01.t - test auto::libjit 
     47 
     48=head1 SYNOPSIS 
     49 
     50    % prove t/steps/auto/libjit-01.t 
     51 
     52=head1 DESCRIPTION 
     53 
     54The files in this directory test functionality used by F<Configure.pl>. 
     55 
     56The tests in this file test auto::libjit. 
     57 
     58=head1 SEE ALSO 
     59 
     60config::auto::libjit, F<Configure.pl>. 
     61 
     62=cut 
     63 
     64# Local Variables: 
     65#   mode: cperl 
     66#   cperl-indent-level: 4 
     67#   fill-column: 100 
     68# End: 
     69# vim: expandtab shiftwidth=4: 
  • t/steps/gen/libjit-01.t

     
     1#! perl 
     2# Copyright (C) 2009, Parrot Foundation. 
     3# $Id$ 
     4# gen/libjit-01.t 
     5 
     6use strict; 
     7use warnings; 
     8 
     9use constant num_generated_files => 2; 
     10use Test::More tests => 8 + 2*num_generated_files; 
     11 
     12use File::Copy 'move'; 
     13use File::Temp 'tempfile'; 
     14 
     15use lib 'lib'; 
     16use Parrot::Configure; 
     17use Parrot::Configure::Options 'process_options'; 
     18use Parrot::Configure::Test qw( 
     19    test_step_thru_runstep 
     20    rerun_defaults_for_testing 
     21    test_step_constructor_and_description 
     22); 
     23 
     24use_ok('config::gen::libjit'); 
     25 
     26my ($args, $step_list_ref) = process_options( 
     27    { 
     28        argv => [], 
     29        mode => 'configure', 
     30    } 
     31); 
     32 
     33my $conf = Parrot::Configure->new; 
     34 
     35my $serialized = $conf->pcfreeze(); 
     36 
     37my $pkg = 'gen::libjit'; 
     38$conf->add_steps($pkg); 
     39$conf->options->set( %$args ); 
     40my $step = test_step_constructor_and_description($conf); 
     41 
     42is( scalar keys %{$step->{targets}}, num_generated_files, "Expected number of generated files"); 
     43is_deeply([keys %{$step->{targets}}], [keys %{$step->{templates}}], "Templates match targets"); 
     44 
     45foreach (keys %{$step->{templates}}) { 
     46    ok(-f $step->{templates}{$_}, "Able to locate $_ template") 
     47} 
     48 
     49my %orig_files; 
     50foreach (keys %{$step->{targets}}) { 
     51    if (-f (my $targ_name = $step->{targets}{$_})) { 
     52        $orig_files{$_} = tempfile(); 
     53        move($targ_name, $orig_files{$_}); 
     54    } 
     55} 
     56 
     57my %orig_conf = map { $_ => $conf->data->get($_) } qw[ iv nv ]; 
     58$conf->data->set( iv => 'int', nv => 'float' ); 
     59my $ret = $step->runstep($conf); 
     60ok( $ret, "runstep() returned true value" ); 
     61foreach (keys %{$step->{targets}}) { 
     62    ok(-f $step->{targets}{$_}, "$_ target generated"); 
     63} 
     64 
     65# re-set for next test 
     66$conf->data->set(%orig_conf); 
     67$step->set_result( '' ); 
     68foreach (keys %{$step->{targets}}) { 
     69    if (exists $orig_files{$_}) { 
     70        move( $orig_files{$_}, $step->{targets}{$_} ); 
     71    } else { 
     72        unlink $_; 
     73    } 
     74} 
     75 
     76$conf->replenish($serialized); 
     77 
     78pass("Completed all tests in $0"); 
     79 
     80################### DOCUMENTATION ################### 
     81 
     82=head1 NAME 
     83 
     84  gen/libjit-01.t - test gen::libjit 
     85 
     86=head1 SYNOPSIS 
     87 
     88    % prove t/steps/gen/libjit-01.t 
     89 
     90=head1 DESCRIPTION 
     91 
     92The files in this directory test functionality used by F<Configure.pl>. 
     93 
     94The tests in this file test gen::libjit. 
     95 
     96=head1 SEE ALSO 
     97 
     98config::gen::libjit, F<Configure.pl>. 
     99 
     100=cut 
     101 
     102# Local Variables: 
     103#   mode: cperl 
     104#   cperl-indent-level: 4 
     105#   fill-column: 100 
     106# End: 
     107# vim: expandtab shiftwidth=4: 
  • config/auto/libjit.pm

     
     1# Copyright (C) 2009, Parrot Foundation. 
     2# $Id$ 
     3 
     4=head1 NAME 
     5 
     6config/auto/libjit - Check whether LibJIT is installed 
     7 
     8=head1 DESCRIPTION 
     9 
     10Determines whether LibJIT is present is installed and 
     11functional on the system. It is OK when it doesn't exist. 
     12 
     13=cut 
     14 
     15package auto::libjit; 
     16 
     17use strict; 
     18use warnings; 
     19 
     20use base 'Parrot::Configure::Step'; 
     21 
     22use Parrot::Configure::Utils ':auto'; 
     23 
     24sub _init { 
     25    my $self = shift; 
     26    my %data = ( 
     27        description => 'Is LibJIT installed', 
     28        result      => '', 
     29    ); 
     30    return \%data; 
     31} 
     32 
     33sub runstep { 
     34    my ($self, $conf) = @_; 
     35 
     36    my ($verbose, $without) = $conf->options->get( qw{ 
     37                                    verbose 
     38                                    without-libjit 
     39    }); 
     40 
     41    if ($without) { 
     42        $conf->data->set( HAS_LIBJIT => 0 ); 
     43        $self->set_result('no'); 
     44        return 1; 
     45    } 
     46 
     47    my $extra_libs = $self->_select_lib({ 
     48        conf         => $conf, 
     49        osname       => $conf->data->get_p5('OSNAME'), 
     50        cc           => $conf->data->get('cc'), 
     51        win32_nongcc => 'libjit.lib', 
     52        default      => '-ljit', 
     53    }); 
     54 
     55    $conf->cc_gen('config/auto/libjit/libjit_c.in'); 
     56    eval {$conf->cc_build('', $extra_libs)}; 
     57    my $has_libjit = 0; 
     58    if (!$@) { 
     59        my $test = $conf->cc_run(); 
     60        $has_libjit = $self->_evaluate_cc_run($conf, $test, $has_libjit, $verbose); 
     61    } else { 
     62        die $@; 
     63    } 
     64 
     65    $conf->data->set( HAS_LIBJIT => $has_libjit ); 
     66    $self->set_result( $has_libjit ? 'yes' : 'no' ); 
     67 
     68    if ($has_libjit) { 
     69        $conf->data->set( 
     70            cc_build_call_frames => '-DCAN_BUILD_CALL_FRAMES', 
     71            has_exec_protect => 1, 
     72        ); 
     73        $conf->data->add( ' ', libs => $extra_libs ); 
     74    } 
     75 
     76    return 1; 
     77} 
     78 
     79sub _evaluate_cc_run { 
     80    my $self = shift; 
     81    my ($conf, $test, $has_libjit, $verbose) = @_; 
     82    if ($test =~ m/^USES INTERPRETER: \d+/ ) { 
     83        $has_libjit = 1; 
     84        print " (yes) " if $verbose; 
     85        $self->set_result("yes"); 
     86    } 
     87    return $has_libjit; 
     88} 
     89 
     901; 
     91 
     92# Local Variables: 
     93#   mode: cperl 
     94#   cperl-indent-level: 4 
     95#   fill-column: 100 
     96# End: 
     97# vim: expandtab shiftwidth=4: 
  • config/auto/libjit/libjit_c.in

     
     1/*  
     2 * Copyright (C) 2009, Parrot Foundation. 
     3 * $Id$ 
     4 */ 
     5 
     6#include <stdlib.h> 
     7#include <stdio.h> 
     8#include <jit/jit.h> 
     9 
     10int 
     11main(int argc, char *argv[]) { 
     12    jit_init(); 
     13    printf("USES INTERPRETER: %i\n", jit_uses_interpreter()); 
     14    return EXIT_SUCCESS; 
     15} 
     16 
     17/* 
     18 * Local variables: 
     19 *   c-file-style: "parrot" 
     20 * End: 
     21 * vim: expandtab shiftwidth=4: 
     22 */ 
  • config/gen/libjit.pm

     
     1# Copyright (C) 2009, Parrot Foundation. 
     2# $Id$ 
     3 
     4=head1 NAME 
     5 
     6config/gen/libjit.pm - LibJIT Code Generation 
     7 
     8=head1 DESCRIPTION 
     9 
     10Populate F<config/gen/frame_builder_libjit_h.in> and 
     11F<configu/gen/frame_builder_libjit_c.in> with system appropriate 
     12type information and automatically generated parrot function and 
     13vtable jit wrappers. 
     14 
     15=cut 
     16 
     17package gen::libjit; 
     18 
     19use strict; 
     20use warnings; 
     21 
     22use base 'Parrot::Configure::Step'; 
     23 
     24use Parrot::Configure::Utils ':gen'; 
     25 
     26 
     27sub _init { 
     28    my $self = shift; 
     29    my %data = ( 
     30        description => 'Generate LibJIT specific code', 
     31        result => '', 
     32        targets => { 
     33            frame_builder_h => 'src/frame_builder_libjit.h', 
     34            frame_builder_c => 'src/frame_builder_libjit.c', 
     35        }, 
     36        templates => { 
     37            frame_builder_h => 'config/gen/libjit/frame_builder_libjit_h.in', 
     38            frame_builder_c => 'config/gen/libjit/frame_builder_libjit_c.in', 
     39        }, 
     40        wrapped_vtables => { 
     41            get_integer        => [ ()           => 'INTVAL' ], 
     42            set_integer_native => [ ('INTVAL')   => 'void' ], 
     43            get_pointer        => [ ()           => 'void_ptr' ], 
     44            set_pointer        => [ ('void_ptr') => 'void' ], 
     45        }, 
     46        wrapped_funcs => { 
     47            get_nci_I => [ qw(void_ptr void_ptr sys_int) => 'INTVAL' ], 
     48            get_nci_N => [ qw(void_ptr void_ptr sys_int) => 'FLOATVAL' ], 
     49            get_nci_S => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ], 
     50            get_nci_P => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ], 
     51            get_nci_p => [ qw(void_ptr void_ptr sys_int) => 'void_ptr' ], 
     52 
     53            set_nci_I => [ qw(void_ptr void_ptr INTVAL)   => 'void' ], 
     54            set_nci_N => [ qw(void_ptr void_ptr FLOATVAL) => 'void' ], 
     55            set_nci_S => [ qw(void_ptr void_ptr void_ptr) => 'void' ], 
     56            set_nci_P => [ qw(void_ptr void_ptr void_ptr) => 'void' ], 
     57 
     58            Parrot_str_new          => [ qw(void_ptr void_ptr UINTVAL) => 'void_ptr' ], 
     59            Parrot_str_to_cstring   => [ qw(void_ptr void_ptr)         => 'void_ptr' ], 
     60            Parrot_str_free_cstring => [ ('void_ptr')                  => 'void' ], 
     61 
     62            Parrot_init_arg_nci => [ qw(void_ptr void_ptr void_ptr) => 'void_ptr' ], 
     63            pmc_new_noinit      => [ qw(void_ptr INTVAL)            => 'void_ptr' ], 
     64        }, 
     65    ); 
     66    return \%data; 
     67} 
     68 
     69sub runstep { 
     70    my ($self, $conf) = @_; 
     71 
     72    my ($libjit_iv, $libjit_uv) = @{ 
     73        my $iv = $conf->data->get('iv') || ''; 
     74        { 
     75            short       => [ 'jit_type_sys_short'   , 'jit_type_sys_ushort' ], 
     76            int         => [ 'jit_type_sys_int'     , 'jit_type_sys_uint' ], 
     77            long        => [ 'jit_type_sys_long'    , 'jit_type_sys_ulong' ], 
     78            'long long' => [ 'jit_type_sys_longlong', 'jit_type_sys_ulonglong' ], 
     79        }->{$iv} 
     80            or die "Couldn't determine libjity type for intval of type '$iv'"; 
     81    }; 
     82 
     83    my $libjit_nv = do { 
     84        my $nv = $conf->data->get('nv') || ''; 
     85        { 
     86            float         => 'jit_type_sys_float', 
     87            double        => 'jit_type_sys_double', 
     88            'long double' => 'jit_type_sys_long_double', 
     89        }->{$nv} 
     90            or die "Couldn't determine libjity type for floatval of type '$nv'"; 
     91    }; 
     92 
     93    $conf->data->set( libjit_iv => $libjit_iv, 
     94                      libjit_uv => $libjit_uv, 
     95                      libjit_nv => $libjit_nv, ); 
     96 
     97    my @vtable_wrappers   = map {gen_vtable_wrapper($self, $_)}   keys %{$self->{wrapped_vtables}}; 
     98    my @function_wrappers = map {gen_function_wrapper($self, $_)} keys %{$self->{wrapped_funcs}}; 
     99 
     100    $conf->data->set( TEMP_vtable_wrap_decls => (join "\n", map {$_->{decl}} @vtable_wrappers), 
     101                      TEMP_vtable_wrap_defns => (join "\n", map {$_->{defn}} @vtable_wrappers), 
     102                      TEMP_func_wrap_decls   => (join "\n", map {$_->{decl}} @function_wrappers), 
     103                      TEMP_func_wrap_defns   => (join "\n", map {$_->{defn}} @function_wrappers) ); 
     104 
     105    foreach (keys %{$self->{targets}}) { 
     106        $conf->genfile($self->{templates}{$_}, $self->{targets}{$_}); 
     107    } 
     108 
     109    return 1; 
     110} 
     111 
     112sub gen_vtable_wrapper { 
     113    my ($self, $entry_name) = @_; 
     114 
     115    my $entry_sig = $self->{wrapped_vtables}{$entry_name}; 
     116    $_ = jit_prefix_type($_) for @$entry_sig; 
     117 
     118    my $ret_t = pop @$entry_sig; 
     119    my $arg_t = join ", ", @$entry_sig; 
     120 
     121    my $n_args      = scalar @$entry_sig; 
     122    my $arg_decls_t = join ", ", map {'jit_value_t'}     1..$n_args; 
     123    my $arg_decls_v = join ", ", map {"jit_value_t v$_"} 1..$n_args; 
     124    my $arg_v       = join ", ", map {"v$_"}             1..$n_args; 
     125 
     126    my $_arg_decls_t = $n_args ? ", $arg_decls_t" : ""; 
     127    my $_arg_decls_v = $n_args ? ", $arg_decls_v" : ""; 
     128    my $_arg_t = $n_args ? ", $arg_t" : ""; 
     129    my $_arg_v = $n_args ? ", $arg_v" : ""; 
     130 
     131    return { decl => <<DECL, defn => <<DEFN }; 
     132jit_value_t 
     133jit__vtable_$entry_name(jit_function_t, jit_value_t, jit_value_t $_arg_decls_t); 
     134DECL 
     135jit_value_t 
     136jit__vtable_$entry_name(jit_function_t f, jit_value_t interp, jit_value_t self $_arg_decls_v) { 
     137    jit_type_t sig; 
     138    jit_value_t vtable, method; 
     139    jit_type_t  arg_t[] = { jit_type_void_ptr, jit_type_void_ptr $_arg_t }; 
     140    jit_value_t arg_v[] = { interp, self $_arg_v }; 
     141 
     142    sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, $n_args + 2, 1); 
     143 
     144    vtable = jit_insn_load_relative(f, self,   offsetof(PMC, vtable),         jit_type_void_ptr); 
     145    method = jit_insn_load_relative(f, vtable, offsetof(VTABLE, $entry_name), jit_type_void_ptr); 
     146 
     147    return jit_insn_call_indirect(f, method, sig, arg_v, $n_args + 2, 0); 
     148} 
     149DEFN 
     150} 
     151 
     152sub gen_function_wrapper { 
     153    my ($self, $func_name) = @_; 
     154 
     155    my $func_sig = $self->{wrapped_funcs}{$func_name}; 
     156    $_ = jit_prefix_type($_) for @$func_sig; 
     157 
     158    my $ret_t = pop @$func_sig; 
     159    my $arg_t = join ", ", @$func_sig; 
     160 
     161    my $n_args      = scalar @$func_sig; 
     162    my $arg_decls_t = join ", ",  map {'jit_value_t'}     1..$n_args; 
     163    my $arg_decls_v = join ", ",  map {"jit_value_t v$_"} 1..$n_args; 
     164    my $arg_v       = join ", ", map {"v$_"}             1..$n_args; 
     165 
     166    return { decl => <<DECL, defn => <<DEFN }; 
     167jit_value_t 
     168jit__$func_name(jit_function_t, $arg_decls_t); 
     169DECL 
     170jit_value_t 
     171jit__$func_name(jit_function_t f, $arg_decls_v) { 
     172    jit_type_t sig; 
     173    jit_type_t  arg_t[] = { $arg_t }; 
     174    jit_value_t arg_v[] = { $arg_v }; 
     175 
     176    sig = jit_type_create_signature(jit_abi_cdecl, $ret_t, arg_t, $n_args, 1); 
     177 
     178    return jit_insn_call_native(f, "$func_name", (void *)&$func_name, sig, arg_v, $n_args, 0); 
     179} 
     180DEFN 
     181} 
     182 
     183sub jit_prefix_type { 
     184    my $type = shift; 
     185    if ($type !~ /[A-Z]/) { 
     186        return "jit_type_$_"; 
     187    } else { 
     188        return "JIT_TYPE_$_"; 
     189    } 
     190} 
     191 
     1921; 
     193 
     194# Local Variables: 
     195#   mode: cperl 
     196#   cperl-indent-level: 4 
     197#   fill-column: 100 
     198# End: 
     199# vim: expandtab shiftwidth=4: 
  • config/gen/makefiles/root.in

     
    217217    myconfig  \ 
    218218    $(GEN_PASM_INCLUDES) \ 
    219219    $(SRC_DIR)/call_list.txt \ 
     220    $(SRC_DIR)/frame_builder_libjit.h \ 
     221    $(SRC_DIR)/frame_builder_libjit.c \ 
    220222    MANIFEST.configure.generated \ 
    221223    .configure_trace.sto \ 
    222224    .parrot_current_rev 
     
    440442    $(SRC_DIR)/misc$(O) \ 
    441443    $(SRC_DIR)/multidispatch$(O) \ 
    442444    $(SRC_DIR)/frame_builder$(O) \ 
     445    $(SRC_DIR)/frame_builder_libjit$(O) \ 
    443446    $(SRC_DIR)/nci$(O) \ 
    444447    $(SRC_DIR)/oo$(O) \ 
    445448    $(SRC_DIR)/packfile$(O) \ 
     
    622625    $(SRC_DIR)/library.str \ 
    623626    $(SRC_DIR)/multidispatch.str \ 
    624627    $(SRC_DIR)/frame_builder.str \ 
     628    $(SRC_DIR)/frame_builder_libjit.str \ 
    625629    $(SRC_DIR)/nci.str \ 
    626630    $(SRC_DIR)/packfile.str \ 
    627631    $(SRC_DIR)/pmc.str \ 
     
    11911195 
    11921196$(SRC_DIR)/nci$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/nci.c $(SRC_DIR)/nci.str \ 
    11931197        $(SRC_DIR)/frame_builder$(O) \ 
     1198        $(SRC_DIR)/frame_builder_libjit$(O) \ 
    11941199        $(SRC_DIR)/pmc/pmc_managedstruct.h \ 
    11951200        $(SRC_DIR)/pmc/pmc_nci.h \ 
    11961201        $(SRC_DIR)/pmc/pmc_pointer.h 
    11971202 
    1198 $(SRC_DIR)/frame_builder$(O) : $(SRC_DIR)/frame_builder.h $(GENERAL_H_FILES) $(SRC_DIR)/frame_builder.c $(SRC_DIR)/frame_builder.str 
     1203$(SRC_DIR)/frame_builder$(O) : \ 
     1204    $(SRC_DIR)/frame_builder.h \ 
     1205    $(SRC_DIR)/frame_builder.c \ 
     1206    $(SRC_DIR)/frame_builder.str \ 
     1207    $(INC_DIR)/parrot.h 
    11991208 
     1209$(SRC_DIR)/frame_builder_libjit$(O) : \ 
     1210    $(SRC_DIR)/frame_builder_libjit.h \ 
     1211    $(SRC_DIR)/frame_builder_libjit.c \ 
     1212    $(SRC_DIR)/frame_builder_libjit.str \ 
     1213    $(SRC_DIR)/frame_builder.h \ 
     1214    $(SRC_DIR)/pmc/pmc_integer.h \ 
     1215    $(SRC_DIR)/pmc/pmc_unmanagedstruct.h \ 
     1216    $(SRC_DIR)/pmc/pmc_managedstruct.h \ 
     1217    $(INC_DIR)/parrot.h 
     1218 
    12001219$(SRC_DIR)/vtables$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/vtables.c 
    12011220 
    12021221$(SRC_DIR)/gc/system$(O) : $(GENERAL_H_FILES)  $(SRC_DIR)/gc/gc_private.h 
  • config/gen/libjit/frame_builder_libjit_c.in

     
     1/* 
     2Copyright (C) 2008-2009, Parrot Foundation. 
     3$Id$ 
     4*/ 
     5 
     6/* HEADERIZER HFILE: none */ 
     7/* HEADERIZER STOP */ 
     8 
     9#include "parrot/parrot.h" 
     10#include "pmc/pmc_integer.h" 
     11#include "pmc/pmc_unmanagedstruct.h" 
     12#include "pmc/pmc_managedstruct.h" 
     13#include "frame_builder.h" 
     14#include "frame_builder_libjit.h" 
     15 
     16#if PARROT_HAS_LIBJIT 
     17 
     18/* 
     19 
     20=over 4 
     21 
     22=item C<void *Parrot_jit_build_call_func(PARROT_INTERP, PMC *nci, STRING *sig, void **priv)> 
     23 
     24Public interface to NCI function interface builder. 
     25 
     26=cut 
     27 
     28*/ 
     29 
     30void * 
     31Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc, STRING *sig, void **priv) { 
     32    void *thunk; 
     33    char *sig_cstr; 
     34 
     35    sig_cstr = Parrot_str_to_cstring(interp, sig); 
     36    *priv    = mem_sys_allocate(sizeof (struct jit_buffer_private_data)); 
     37 
     38    thunk    = Parrot_jit_create_thunk(interp, sig_cstr, *priv); 
     39 
     40    Parrot_str_free_cstring(sig_cstr); 
     41 
     42    return thunk; 
     43} 
     44 
     45/* 
     46 
     47=item C<void Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv)> 
     48 
     49This is a callback to implement the proper freeing semantics.  It is called by 
     50the ManagedStruct PMC as it is garbage collected. 
     51 
     52=cut 
     53 
     54*/ 
     55 
     56void 
     57Parrot_jit_free_buffer(PARROT_INTERP, void *ptr, void *priv) 
     58{ 
     59    struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; 
     60    jit_context_destroy(jit->ctx); 
     61    mem_sys_free(jit->sig); 
     62    mem_sys_free(priv); 
     63} 
     64 
     65/* 
     66 
     67=item C<PMC *Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv)> 
     68 
     69This is a callback to implement the proper cloning semantics for jit buffers. 
     70It is called by the ManagedStruct PMC's clone() function. 
     71 
     72=back 
     73 
     74=cut 
     75 
     76*/ 
     77 
     78PMC * 
     79Parrot_jit_clone_buffer(PARROT_INTERP, PMC *pmc, void *priv) 
     80{ 
     81    PMC * const rv = pmc_new(interp, pmc->vtable->base_type); 
     82 
     83    VTABLE_init(interp, rv); 
     84    /* copy the attributes */ 
     85    { 
     86        void (*tmpfreefunc)(PARROT_INTERP, void*, void*); 
     87        GETATTR_ManagedStruct_custom_free_func(interp, pmc, tmpfreefunc); 
     88        SETATTR_ManagedStruct_custom_free_func(interp, rv , tmpfreefunc); 
     89    } 
     90    { 
     91        PMC* (*tmpclonefunc)(PARROT_INTERP, PMC*, void*); 
     92        GETATTR_ManagedStruct_custom_clone_func(interp, pmc, tmpclonefunc); 
     93        SETATTR_ManagedStruct_custom_clone_func(interp, rv , tmpclonefunc); 
     94    } 
     95 
     96    /* compile a clone of the function */ 
     97    if (PARROT_MANAGEDSTRUCT(pmc)->ptr) { 
     98        void *rv_priv; 
     99        struct jit_buffer_private_data *jit = (struct jit_buffer_private_data*)priv; 
     100        STRING *sig                         = Parrot_str_new(interp, jit->sig, 0); 
     101        PARROT_MANAGEDSTRUCT(rv)->ptr       = Parrot_jit_build_call_func(interp, rv, sig, &rv_priv); 
     102    } 
     103 
     104    return rv; 
     105} 
     106 
     107/* 
     108 * JIT functions 
     109 */ 
     110 
     111void * 
     112Parrot_jit_create_thunk(PARROT_INTERP, char *sig, void *priv) { 
     113    struct jit_buffer_private_data *p; 
     114    jit_function_t f; 
     115    jit_value_t jit_interp, jit_func; 
     116    jit_type_t *jit_args_t; 
     117    jit_value_t *jit_args_v, *jit_regs; 
     118 
     119    /* populate private data */ 
     120    p      = (struct jit_buffer_private_data*)priv; 
     121    p->ctx = jit_context_create(); 
     122    p->sig = mem_sys_strdup(sig); 
     123 
     124    /* start compiling */ 
     125    jit_context_build_start(p->ctx); 
     126 
     127    /* start JIT function */ 
     128    { 
     129        jit_type_t arg_types[] = { 
     130            jit_type_void_ptr,  /* interp */ 
     131            jit_type_void_ptr   /* nci_info */ 
     132        }; 
     133        jit_type_t f_sig = jit_type_create_signature(jit_abi_cdecl, jit_type_void, arg_types, 2, 1); 
     134        f                = jit_function_create(p->ctx, f_sig); 
     135    } 
     136 
     137    /* get the incomming args */ 
     138    jit_interp = jit_value_get_param(f, 0); 
     139    jit_func   = jit__vtable_get_pointer(f, jit_interp, jit_value_get_param(f, 1)); 
     140 
     141    /* get the outgoing args */ 
     142    { 
     143        jit_value_t st; 
     144        int nargs; 
     145 
     146        { 
     147            jit_value_t sizeof_call_state 
     148                = jit_value_create_nint_constant(f, jit_type_sys_int, sizeof (call_state)); 
     149            st  = jit_insn_alloca(f, sizeof_call_state); 
     150        } 
     151 
     152        nargs = Parrot_jit_parse_sig_args_pre(interp, sig, f, jit_interp, st, 
     153                                              &jit_args_t, &jit_args_v, &jit_regs); 
     154 
     155        /* get the return type */ 
     156        { 
     157            jit_type_t ret_t; 
     158            jit_value_t ret_v; 
     159 
     160            ret_t = Parrot_jit_parse_sig_ret_pre(interp, sig); 
     161 
     162            /* make the call */ 
     163            { 
     164                jit_type_t jit_sig 
     165                          = jit_type_create_signature(jit_abi_cdecl, ret_t, jit_args_t, nargs, 1); 
     166                ret_v     = jit_insn_call_indirect(f, jit_func, jit_sig, jit_args_v, nargs, 0); 
     167            } 
     168 
     169            /* get the incomming return */ 
     170            Parrot_jit_parse_sig_ret_post(interp, sig, f, jit_interp, st, ret_v); 
     171        } 
     172 
     173        /* clean up args */ 
     174        Parrot_jit_parse_sig_args_post(interp, sig, nargs, f, jit_interp, jit_args_v, jit_regs); 
     175    } 
     176 
     177    /* end JIT function */ 
     178    jit_insn_return(f, NULL); 
     179 
     180    /* compile to native callable func poitner */ 
     181    jit_function_compile(f); 
     182    jit_context_build_end(p->ctx); 
     183 
     184    mem_sys_free(jit_args_t); 
     185    mem_sys_free(jit_args_v); 
     186    mem_sys_free(jit_regs); 
     187 
     188    return jit_function_to_closure(f); 
     189} 
     190 
     191int 
     192Parrot_jit_parse_sig_args_pre(PARROT_INTERP, char *sig, jit_function_t f, 
     193                              jit_value_t jinterp, jit_value_t st, 
     194                              jit_type_t **arg_types, 
     195                              jit_value_t **arg_vals, jit_value_t **arg_regs) { 
     196    int nargs, nregs, i, j; 
     197 
     198    sig += 1; /* ignore return character */ 
     199 
     200    nargs = strlen(sig); 
     201    nregs = Parrot_jit_init_pcc(sig, nargs, f, jinterp, st); 
     202 
     203    *arg_types = (jit_type_t *)mem_sys_allocate(nargs * sizeof (jit_type_t)); 
     204    *arg_vals  = (jit_value_t *)mem_sys_allocate(nargs * sizeof (jit_value_t)); 
     205    *arg_regs  = (jit_value_t *)mem_sys_allocate(nregs * sizeof (jit_value_t)); 
     206 
     207    for (i = 0, j = 0; i < nargs; i++) { 
     208        char c; 
     209        jit_type_t t1; 
     210        jit_value_t v1, v2, v3, v4; 
     211        switch (c = sig[i]) { 
     212          case 'I': 
     213            t1 = JIT_TYPE_INTVAL; 
     214          read_int_reg: 
     215            (*arg_types)[i]  = t1; 
     216            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     217            v2               = jit__get_nci_I(f, jinterp, st, v1); 
     218            (*arg_regs)[j++] = (*arg_vals)[i] = v2; 
     219            break; 
     220          case 'c': 
     221            t1 = jit_type_sys_char; 
     222            goto read_int_reg; 
     223          case 's': 
     224            t1 = jit_type_sys_short; 
     225            goto read_int_reg; 
     226          case 'i': 
     227            t1 = jit_type_sys_int; 
     228            goto read_int_reg; 
     229          case 'l': 
     230            t1 = jit_type_sys_long; 
     231            goto read_int_reg; 
     232 
     233          case 'N': 
     234            t1 = JIT_TYPE_FLOATVAL; 
     235          read_float_reg: 
     236            (*arg_types)[i]  = t1; 
     237            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     238            v2               = jit__get_nci_N(f, jinterp, st, v1); 
     239            (*arg_regs)[j++] = (*arg_vals)[i] = v2; 
     240            break; 
     241          case 'f': 
     242            t1 = jit_type_sys_float; 
     243            goto read_float_reg; 
     244          case 'd': 
     245            t1 = jit_type_sys_double; 
     246            goto read_float_reg; 
     247 
     248          case 'S': 
     249            (*arg_types)[i]  = jit_type_void_ptr; 
     250            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     251            v2               = jit__get_nci_S(f, jinterp, st, v1); 
     252            (*arg_regs)[j++] = (*arg_vals)[i] = v2; 
     253            break; 
     254 
     255          case 't': 
     256            (*arg_types)[i]  = jit_type_void_ptr; 
     257            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     258            v2               = jit__get_nci_S(f, jinterp, st, v1); 
     259            (*arg_regs)[j++] = v2; 
     260            (*arg_vals)[i]   = jit__Parrot_str_to_cstring(f, jinterp, v2); 
     261            break; 
     262 
     263          case 'b': 
     264            (*arg_types)[i]  = jit_type_void_ptr; 
     265            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     266            v2               = jit__get_nci_S(f, jinterp, st, v1); 
     267            (*arg_regs)[j++] = v2; 
     268            (*arg_vals)[i]   = jit__Buffer_bufstart(f, v2); 
     269            break; 
     270          case 'B': 
     271            (*arg_types)[i]  = jit_type_void_ptr; 
     272            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     273            v2               = jit__get_nci_S(f, jinterp, st, v1); 
     274            (*arg_regs)[j++] = v2; 
     275            v3               = jit__Parrot_str_to_cstring(f, jinterp, v2); 
     276            jit_value_set_addressable(v3); 
     277            (*arg_vals)[i]   = jit_insn_address_of(f, v3); 
     278            break; 
     279 
     280          case 'p': 
     281            (*arg_types)[i]  = jit_type_void_ptr; 
     282            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     283            v2               = jit__get_nci_p(f, jinterp, st, v1); 
     284            (*arg_regs)[j++] = (*arg_vals)[i] = v2; 
     285            break; 
     286          case 'P': 
     287          case 'O': 
     288          case '@': 
     289            (*arg_types)[i]  = jit_type_void_ptr; 
     290            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     291            v2               = jit__get_nci_P(f, jinterp, st, v1); 
     292            (*arg_regs)[j++] = (*arg_vals)[i] = v2; 
     293            break; 
     294          case '2': 
     295            t1 = jit_type_sys_short; 
     296            goto call_get_integer; 
     297          case '3': 
     298            t1 = jit_type_sys_int; 
     299            goto call_get_integer; 
     300          case '4': 
     301            t1 = jit_type_sys_long; 
     302          call_get_integer: 
     303            (*arg_types)[i]  = jit_type_void_ptr; 
     304            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     305            v2               = jit__get_nci_P(f, jinterp, st, v1); 
     306            (*arg_regs)[j++] = v2; 
     307            v3               = jit__vtable_get_integer(f, jinterp, v2); 
     308            v4               = jit_value_create(f, t1); 
     309            jit_value_set_addressable(v4); 
     310            jit_insn_store(f, v4, v3); 
     311            (*arg_vals)[i]   = jit_insn_address_of(f, v4); 
     312            break; 
     313 
     314          case 'V': 
     315            (*arg_types)[i]  = jit_type_void_ptr; 
     316            v1               = jit_value_create_nint_constant(f, jit_type_sys_int, j); 
     317            v2               = jit__get_nci_P(f, jinterp, st, v1); 
     318            (*arg_regs)[j++] = v2; 
     319            v3               = jit__vtable_get_pointer(f, jinterp, v2); 
     320            v4               = jit_value_create(f, jit_type_void_ptr); 
     321            jit_value_set_addressable(v4); 
     322            jit_insn_store(f, v4, v3); 
     323            (*arg_vals)[i]   = jit_insn_address_of(f, v4); 
     324            break; 
     325 
     326          case '0': 
     327            (*arg_types)[i] = jit_type_void_ptr; 
     328            (*arg_vals)[i]  = jit_value_create_nint_constant(f, jit_type_void_ptr, (jit_nint)NULL); 
     329            break; 
     330 
     331          case 'J': 
     332            (*arg_types)[i] = jit_type_void_ptr; 
     333            (*arg_vals)[i]  = jinterp; 
     334            break; 
     335 
     336          case 'U': 
     337            /* TODO */ 
     338            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
     339                "arg type 'U' not yet implemented"); 
     340            return -1; 
     341 
     342          default: 
     343            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
     344                "unkown arg type '%c'", c); 
     345            return -1; 
     346        } 
     347    } 
     348 
     349    return nargs; 
     350} 
     351 
     352int 
     353Parrot_jit_init_pcc(char *sig, int nargs, jit_function_t f, jit_value_t interp, jit_value_t st) { 
     354    int i, j; 
     355    char pcc_sig[nargs]; 
     356 
     357    for (i = 0, j = 0; i < nargs; i++) { 
     358        switch (sig[i]) { 
     359          case 'I': 
     360          case 'c': 
     361          case 's': 
     362          case 'i': 
     363          case 'l': 
     364            pcc_sig[j++] = 'I'; 
     365            break; 
     366 
     367          case 'N': 
     368          case 'f': 
     369          case 'd': 
     370            pcc_sig[j++] = 'N'; 
     371            break; 
     372 
     373          case 'S': 
     374          case 't': 
     375          case 'b': 
     376          case 'B': 
     377            pcc_sig[j++] = 'S'; 
     378            break; 
     379 
     380          case 'p': 
     381          case 'P': 
     382          case 'O': 
     383          case 'V': 
     384          case '2': 
     385          case '3': 
     386          case '4': 
     387            pcc_sig[j++] = 'P'; 
     388            break; 
     389 
     390          case '@': 
     391            pcc_sig[j++] = '@'; 
     392            break; 
     393 
     394          default: 
     395            break; 
     396        } 
     397    } 
     398    pcc_sig[j]  = '\0'; 
     399 
     400    jit__Parrot_init_arg_nci(f, interp, st, 
     401                             jit_value_create_string_constant(f, pcc_sig, j+1)); 
     402 
     403    return j; 
     404} 
     405 
     406jit_type_t 
     407Parrot_jit_parse_sig_ret_pre(PARROT_INTERP, char *sig) { 
     408    char c; 
     409    switch (c = sig[0]) { 
     410      case 'v': 
     411        return jit_type_void; 
     412 
     413      case 'I': 
     414        return JIT_TYPE_INTVAL; 
     415      case 'c': 
     416        return jit_type_sys_char; 
     417      case 's': 
     418        return jit_type_sys_short; 
     419      case 'i': 
     420        return jit_type_sys_int; 
     421      case 'l': 
     422        return jit_type_sys_long; 
     423 
     424      case 'N': 
     425        return JIT_TYPE_FLOATVAL; 
     426      case 'f': 
     427        return jit_type_sys_float; 
     428      case 'd': 
     429        return jit_type_sys_double; 
     430 
     431      case 'S': 
     432      case 't': 
     433        return jit_type_void_ptr; 
     434 
     435      case 'p': 
     436      case 'P': 
     437        return jit_type_void_ptr; 
     438 
     439      case 'U': 
     440        /* TODO */ 
     441        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
     442                                    "return type 'U' not yet implemented"); 
     443        return NULL; 
     444      default: 
     445        /* FAIL */ 
     446        Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, 
     447                                    "unknown return type '%c'", c); 
     448        return NULL; 
     449    } 
     450} 
     451 
     452void 
     453Parrot_jit_parse_sig_ret_post(PARROT_INTERP, char *sig, 
     454                              jit_function_t f, jit_value_t jinterp, jit_value_t st, 
     455                              jit_value_t retval) { 
     456    jit_type_t t1; 
     457    jit_value_t v1, v2, v3; 
     458    switch (sig[0]) { 
     459      case 'v': 
     460        break; 
     461 
     462      case 'I': 
     463      case 'c': 
     464      case 's': 
     465      case 'i': 
     466      case 'l': 
     467        jit__set_nci_I(f, jinterp, st, retval); 
     468        break; 
     469 
     470      case 'N': 
     471      case 'f': 
     472      case 'd': 
     473        jit__set_nci_N(f, jinterp, st, retval); 
     474        break; 
     475 
     476      case 'S': 
     477        jit__set_nci_S(f, jinterp, st, retval); 
     478        break; 
     479      case 't': 
     480        v1 = jit_value_create_nint_constant(f, jit_type_sys_int, 0); 
     481        v2 = jit__Parrot_str_new(f, jinterp, retval, v1); 
     482        jit__set_nci_S(f, jinterp, st, v2); 
     483        break; 
     484 
     485      case 'P': 
     486        jit__set_nci_P(f, jinterp, st, retval); 
     487        break; 
     488      case 'p': 
     489        v1 = jit_value_create_intval_constant(f, enum_class_UnManagedStruct); 
     490        v2 = jit__pmc_new_noinit(f, jinterp, v1); 
     491        jit__vtable_set_pointer(f, jinterp, v2, retval); 
     492        jit__set_nci_P(f, jinterp, st, v2); 
     493        break; 
     494      case '2': 
     495        t1 = jit_type_sys_short; 
     496        goto create_int_pmc; 
     497      case '3': 
     498        t1 = jit_type_sys_int; 
     499        goto create_int_pmc; 
     500      case '4': 
     501        t1 = jit_type_sys_long; 
     502      create_int_pmc: 
     503        v1 = jit_insn_load_relative(f, retval, 0, t1); 
     504        v2 = jit_value_create_intval_constant(f, enum_class_Integer); 
     505        v3 = jit__pmc_new_noinit(f, jinterp, v2); 
     506        jit__vtable_set_integer_native(f, jinterp, v3, v1); 
     507        jit__set_nci_P(f, jinterp, st, v3); 
     508        break; 
     509 
     510      case 'U': 
     511        /* ignore (failed elsewhere) */ 
     512        break; 
     513 
     514      default: 
     515        /* ignore (failed elsewhere) */ 
     516        break; 
     517    } 
     518} 
     519 
     520void 
     521Parrot_jit_parse_sig_args_post(PARROT_INTERP, char *sig, int nargs, 
     522                               jit_function_t f, jit_value_t jinterp, 
     523                               jit_value_t *args, jit_value_t *regs) { 
     524    int i, j; 
     525 
     526    sig += 1; 
     527 
     528    for (i = 0, j = 0; i < nargs; i++) { 
     529        jit_type_t t1; 
     530        jit_value_t v1; 
     531        switch (sig[i]) { 
     532          case 't': 
     533            jit__Parrot_str_free_cstring(f, args[i]); 
     534            j++; 
     535            break; 
     536 
     537          case 'B': 
     538            v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr); 
     539            jit__Parrot_str_free_cstring(f, v1); 
     540            j++; 
     541            break; 
     542 
     543          case '2': 
     544            t1 = jit_type_sys_short; 
     545            goto set_integer; 
     546          case '3': 
     547            t1 = jit_type_sys_int; 
     548            goto set_integer; 
     549          case '4': 
     550            t1 = jit_type_sys_long; 
     551          set_integer: 
     552            v1 = jit_insn_load_relative(f, args[i], 0, t1); 
     553            jit__vtable_set_integer_native(f, jinterp, regs[j], v1); 
     554            j++; 
     555            break; 
     556 
     557          case 'V': 
     558            v1 = jit_insn_load_relative(f, args[i], 0, jit_type_void_ptr); 
     559            jit__vtable_set_pointer(f, jinterp, regs[j], v1); 
     560            j++; 
     561            break; 
     562 
     563          case 'I': 
     564          case 'c': 
     565          case 'i': 
     566          case 'l': 
     567          case 'N': 
     568          case 'f': 
     569          case 'd': 
     570          case 'S': 
     571          case 'b': 
     572          case 'p': 
     573          case 'P': 
     574          case 'O': 
     575          case '@': 
     576            j++; 
     577            break; 
     578 
     579          case 'U': 
     580            /* TODO */ 
     581            break; 
     582          default: 
     583            /* ignore */ 
     584            break; 
     585        } 
     586    } 
     587} 
     588 
     589jit_value_t 
     590jit_value_create_intval_constant(jit_function_t f, INTVAL i) { 
     591    return jit_value_create_nint_constant(f, JIT_TYPE_INTVAL, i); 
     592} 
     593 
     594jit_value_t 
     595jit_value_create_string_constant(jit_function_t f, char *str, int len) { 
     596    jit_value_t jit_len, jit_str; 
     597    int i; 
     598 
     599    if (len < 1) { 
     600        len = strlen(str); 
     601    } 
     602 
     603    jit_len = jit_value_create_nint_constant(f, jit_type_sys_int, len); 
     604    jit_str = jit_insn_alloca(f, jit_len); 
     605 
     606    for (i = 0; i < len; i++) { 
     607        jit_value_t c = jit_value_create_nint_constant(f, jit_type_sys_char, str[i]); 
     608        jit_insn_store_relative(f, jit_str, i, c); 
     609    } 
     610 
     611    return jit_str; 
     612} 
     613 
     614/* 
     615 * JIT wrappers 
     616 */ 
     617 
     618/* custom wrappers */ 
     619jit_value_t 
     620jit__Buffer_bufstart(jit_function_t f, jit_value_t buf) { 
     621    return jit_insn_load_relative(f, buf, offsetof(Buffer, _bufstart), jit_type_void_ptr); 
     622} 
     623 
     624/* vtable wrappers */ 
     625@TEMP_vtable_wrap_defns@ 
     626 
     627/* function wrappers */ 
     628@TEMP_func_wrap_defns@ 
     629 
     630#endif /* PARROT_HAS_LIBJIT */ 
     631 
     632/* 
     633 * Local variables: 
     634 *   c-file-style: "parrot" 
     635 * End: 
     636 * vim: expandtab shiftwidth=4: 
     637 */ 
  • config/gen/libjit/frame_builder_libjit_h.in

     
     1/* frame_builder_libjit.h 
     2 * $Id$ 
     3 * Copyright (C) 2009, Parrot Foundation. 
     4 */ 
     5 
     6#ifndef PARROT_FRAME_BUILDER_LIBJIT_H_GUARD 
     7#define PARROT_FRAME_BUILDER_LIBJIT_H_GUARD 
     8 
     9 
     10#if defined(__cplusplus) 
     11#  define EXTERN extern "C" 
     12#else 
     13#  define EXTERN 
     14#endif 
     15 
     16#include <assert.h> 
     17#include "parrot/parrot.h" 
     18#include "frame_builder.h" 
     19 
     20#if PARROT_HAS_LIBJIT 
     21 
     22#include <jit/jit.h> 
     23 
     24/* 
     25 * JITted function state data 
     26 */ 
     27struct jit_buffer_private_data { 
     28    jit_context_t ctx; 
     29    char *sig; 
     30}; 
     31 
     32/* 
     33 * JIT types 
     34 */ 
     35 
     36#define JIT_TYPE_UINTVAL  @libjit_uv@ // jit_type_sys_ulong 
     37#define JIT_TYPE_INTVAL   @libjit_iv@ // jit_type_sys_long 
     38#define JIT_TYPE_FLOATVAL @libjit_nv@ // jit_type_sys_double 
     39 
     40/* 
     41 * JIT functions 
     42 */ 
     43 
     44void * 
     45Parrot_jit_create_thunk(Interp *, char *, void *); 
     46 
     47int 
     48Parrot_jit_parse_sig_args_pre(Interp *, char *, jit_function_t, jit_value_t, jit_value_t, 
     49                              jit_type_t **, jit_value_t **, jit_value_t **); 
     50 
     51int 
     52Parrot_jit_init_pcc(char *, int, jit_function_t, jit_value_t, jit_value_t); 
     53 
     54jit_type_t 
     55Parrot_jit_parse_sig_ret_pre(Interp *, char *); 
     56 
     57void 
     58Parrot_jit_parse_sig_ret_post(Interp *, char *, jit_function_t, jit_value_t, jit_value_t, jit_value_t); 
     59 
     60void 
     61Parrot_jit_parse_sig_args_post(Interp *, char *, int, jit_function_t, jit_value_t, jit_value_t *, jit_value_t *); 
     62 
     63jit_value_t 
     64jit_value_create_intval_constant(jit_function_t, INTVAL); 
     65 
     66jit_value_t 
     67jit_value_create_string_constant(jit_function_t, char *, int); 
     68 
     69/* 
     70 * JIT wrappers 
     71 */ 
     72 
     73/* custom wrappers */ 
     74jit_value_t 
     75jit__Buffer_bufstart(jit_function_t, jit_value_t); 
     76 
     77/* vtable wrappers */ 
     78@TEMP_vtable_wrap_decls@ 
     79 
     80/* function wrappers */ 
     81@TEMP_func_wrap_decls@ 
     82 
     83#endif /* PARROT_HAS_LIBJIT */ 
     84#endif /* PARROT_FRAME_BUILDER_LIBJIT_H_GUARD */ 
     85 
     86/* 
     87 * Local variables: 
     88 *   c-file-style: "parrot" 
     89 * End: 
     90 * vim: expandtab shiftwidth=4: 
     91 */