;
; i386/core.jit
;
; $Id: /mirror/trunk/src/jit/i386/core.jit 32110 2008-10-21T20:35:06.288924Z julianalbo  $
;

# TODO complete this
#define P_ARITH ((PREV_OP == dec_i) || (PREV_OP == inc_i) || (PREV_OP == sub_i_i_i) || (PREV_OP == sub_i_i))

#define CALL_FUNCTION(j, f) call_func(j, (void (*)(void)) & f)

Parrot_end {
    jit_emit_end(NATIVECODE);
}

Parrot_noop {
    emit_nop(NATIVECODE);
}


TEMPLATE Parrot_set_x_x {
    if (MAP[1] && MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
    }
    else if (MAP[2]) {
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), MAP[2]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_set_n_n {
    Parrot_set_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_set_i_i {
    Parrot_set_x_x s/<_N>/_i/
}

Parrot_set_p_p {
    Parrot_set_x_x s/<_N>/_i/ s/INT/PMC/
}

Parrot_set_s_s {
    Parrot_set_x_x s/<_N>/_i/ s/INT/STR/
}

TEMPLATE Parrot_set_x_ic {
    if (MAP[1]) {
        jit_emit_mov_ri<_N>(interp, NATIVECODE, MAP[1], <typ>_CONST[2]);
    }
    else {
        jit_emit_mov_MI<_N>(interp, NATIVECODE, ROFFS_INT(1), <typ>_CONST[2]);
    }
}

Parrot_set_i_ic {
    Parrot_set_x_ic s/<_N>/_i/ s/<typ>/*INT/
}

Parrot_set_n_ic {
    Parrot_set_x_ic s/<_N>/_ni/ s/INT/NUM/ s/<typ>/&INT/
}

Parrot_set_n_nc {
    if (MAP[1]) {
        jit_emit_mov_ri_n(interp, NATIVECODE, MAP[1], &NUM_CONST[2]);
    }
    else {
        jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &NUM_CONST[2]);
        jit_emit_mov_MR_n(interp, NATIVECODE, ROFFS_NUM(1), FSR1);
    }
}

Parrot_set_p_pc {
    if (MAP[1]) {
        jit_emit_mov_rm_i(interp, NATIVECODE, MAP[1], &PMC_CONST[2]);
    }
    else {
        jit_emit_mov_rm_i(interp, NATIVECODE, ISR1, &PMC_CONST[2]);
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_PMC(1), ISR1);
    }
}

Parrot_set_n_i {
; store mapped int
    if (MAP[2]) {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(2), MAP[2]);
    }
    if (MAP[1]) {
        jit_emit_mov_RM_ni(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
    }
    else {
        jit_emit_mov_RM_ni(interp, NATIVECODE, FSR1, ROFFS_INT(2));
        jit_emit_mov_MR_n(interp, NATIVECODE, ROFFS_NUM(1), FSR1);
    }
}

; these are wrong: fist does rounding, but we should truncate
;Parrot_set_i_n {
;    if (MAP[2]) {
;        jit_emit_mov_MR_in(NATIVECODE, ROFFS_INT(1), MAP[2]);
;    }
;    else {
;        jit_emit_mov_RM_n(NATIVECODE, FSR1, ROFFS_NUM(2));
;        jit_emit_mov_MR_in(NATIVECODE, ROFFS_INT(1), FSR1);
;    }
;    if (MAP[1]) {
;        jit_emit_mov_RM_i(interp, NATIVECODE, MAP[1], ROFFS_INT(1));
;    }
;}
;
;Parrot_set_i_nc {
;    jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &NUM_CONST[2]);
;    jit_emit_mov_MR_in(NATIVECODE, ROFFS_INT(1), FSR1);
;    if (MAP[1]) {
;        jit_emit_mov_RM_i(interp, NATIVECODE, MAP[1], ROFFS_INT(1));
;    }
;}

; -- null op.
TEMPLATE Parrot_null_x {
    if (MAP[1]) {
        jit_emit_mov_ri<_N>(interp, NATIVECODE, MAP[1], <val>);
    }
    else {
        jit_emit_mov_MI<_N>(interp, NATIVECODE, ROFFS_INT(1), <val>);
    }
}

Parrot_null_i {
    Parrot_null_x s/<_N>/_i/ s/<val>/0/
}

Parrot_null_p {
    Parrot_null_x s/<_N>/_i/ s/INT/PMC/ s/<val>/PMCNULL/
}

Parrot_null_s {
    Parrot_null_x s/<_N>/_i/ s/INT/STR/ s/<val>/NULL/
}

; TODO use fldz
Parrot_null_n {
    static FLOATVAL zero = 0;
    if (MAP[1]) {
        jit_emit_mov_ri_n(interp, NATIVECODE, MAP[1], &zero);
    }
    else {
        jit_emit_mov_MI_ni(interp, NATIVECODE, ROFFS_NUM(1), &zero);
    }
}

TEMPLATE Parrot_binop_x_x {
    if (MAP[1] && MAP[2]) {
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
    }
    else if (MAP[2]) {
# ifdef jit_emit_<op>_MR<_N>
        jit_emit_<op>_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), MAP[2]);
# else
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(1));
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[2]);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
# endif
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(1));
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

TEMPLATE Parrot_divop_x_x {
    if (MAP[1]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[1]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(1));
    }
    if (MAP[2]) {
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[2]);
    }
    else {
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
    }
    if (MAP[1]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_mul_i_i {
    Parrot_binop_x_x s/<op>/mul/ s/<_N>/_i/
}

Parrot_div_i_i {
    Parrot_divop_x_x s/<op>/div/ s/<_N>/_i/
}

Parrot_add_i_i {
    Parrot_binop_x_x s/<op>/add/ s/<_N>/_i/
}

Parrot_sub_i_i {
    Parrot_binop_x_x s/<op>/sub/ s/<_N>/_i/
}

Parrot_bor_i_i {
    Parrot_binop_x_x s/<op>/bor/ s/<_N>/_i/
}

Parrot_bxor_i_i {
    Parrot_binop_x_x s/<op>/bxor/ s/<_N>/_i/
}

Parrot_band_i_i {
    Parrot_binop_x_x s/<op>/band/ s/<_N>/_i/
}

Parrot_shl_i_i {
    Parrot_binop_x_x s/<op>/shl/ s/<_N>/_i/
}

Parrot_shr_i_i {
    Parrot_binop_x_x s/<op>/shr/ s/<_N>/_i/
}

Parrot_lsr_i_i {
    Parrot_binop_x_x s/<op>/lsr/ s/<_N>/_i/
}

Parrot_mul_n_n {
    Parrot_binop_x_x s/<op>/mul/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_add_n_n {
    Parrot_binop_x_x s/<op>/add/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_sub_n_n {
    Parrot_binop_x_x s/<op>/sub/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_div_n_n {
    Parrot_binop_x_x s/<op>/div/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_exchange_i_i {
    Parrot_binop_x_x s/<op>/xchg/ s/<_N>/_i/
}

Parrot_exchange_s_s {
    Parrot_binop_x_x s/<op>/xchg/ s/<_N>/_i/ s/INT/STR/
}

Parrot_exchange_p_p {
    Parrot_binop_x_x s/<op>/xchg/ s/<_N>/_i/ s/INT/PMC/
}

Parrot_exchange_n_n {
    Parrot_binop_x_x s/<op>/xchg/ s/<_N>/_n/ s/INT/NUM/
}

Parrot_mul_i_i_ic {
    if (MAP[1] && MAP[2]) {
        jit_emit_mul_rir_i(NATIVECODE, MAP[1], *INT_CONST[3], MAP[2]);
    }
    else if (MAP[1]) {
        jit_emit_mul_RIM_ii(NATIVECODE, MAP[1], *INT_CONST[3], ROFFS_INT(2));
    }
    else if (MAP[2]) {
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[3], MAP[2]);
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
    else {
        jit_emit_mov_RM_i(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[3], ISR1);
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_mul_i_ic_i {
    if (MAP[1] && MAP[3]) {
        jit_emit_mul_rir_i(NATIVECODE, MAP[1], *INT_CONST[2], MAP[3]);
    }
    else if (MAP[1]) {
        jit_emit_mul_RIM_ii(NATIVECODE, MAP[1], *INT_CONST[2], ROFFS_INT(3));
    }
    else if (MAP[3]) {
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[2], MAP[3]);
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
    else {
        jit_emit_mul_RIM_ii(NATIVECODE, ISR1, *INT_CONST[2], ROFFS_INT(3));
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

TEMPLATE Parrot_binop_x_xc {
    if (MAP[1]) {
        jit_emit_<op>_ri<_N>(interp, NATIVECODE, MAP[1], <typ>_CONST[2]);
    }
    else {
# ifdef jit_emit_<op>_MI_<_N>
        jit_emit_<op>_MI<_N>(NATIVECODE, ROFFS_INT(1), <typ>_CONST[2]);
# else
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(1));
        jit_emit_<op>_ri<_N>(interp, NATIVECODE, ISR1, <typ>_CONST[2]);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1)
# endif
    }
}

Parrot_add_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/add/ s/<typ>/*INT/
}

Parrot_mul_i_ic {
    if (MAP[1]) {
        jit_emit_mul_rir_i(NATIVECODE, MAP[1], *INT_CONST[2], MAP[1]);
    }
    else  {
        jit_emit_mul_RIM_ii(NATIVECODE, ISR1, *INT_CONST[2], ROFFS_INT(1));
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_div_i_ic {
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, ISR1, MAP[1]);
    }
    else {
        jit_emit_mov_RM_i(interp, NATIVECODE, ISR1, ROFFS_INT(1));
    }
    jit_emit_div_ri_i(NATIVECODE, ISR1, *INT_CONST[2]);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp,NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_add_n_nc {
    Parrot_binop_x_xc s/<_N>/_n/ s/<op>/add/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_sub_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/sub/ s/<typ>/*INT/
}

Parrot_bor_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/bor/ s/<typ>/*INT/
}

Parrot_band_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/band/ s/<typ>/*INT/
}

Parrot_bxor_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/bxor/ s/<typ>/*INT/
}

Parrot_shl_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/shl/ s/<typ>/*INT/
}

Parrot_shr_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/shr/ s/<typ>/*INT/
}

Parrot_lsr_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/lsr/ s/<typ>/*INT/
}

Parrot_sub_n_nc {
    Parrot_binop_x_xc s/<_N>/_n/ s/<op>/sub/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_mul_n_nc {
    Parrot_binop_x_xc s/<_N>/_n/ s/<op>/mul/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_div_n_nc {
    Parrot_binop_x_xc s/<_N>/_n/ s/<op>/div/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

TEMPLATE Parrot_binop_i_ic_ic {
    if (MAP[1]) {
        jit_emit_mov_ri_i(interp, NATIVECODE, MAP[1], (INTVAL)((uicast)*INT_CONST[2] <op> *INT_CONST[3]));
    }
    else {
        jit_emit_mov_MI_i(interp, NATIVECODE, ROFFS_INT(1), (INTVAL)((uicast)*INT_CONST[2] <op> *INT_CONST[3]));
    }
}
Parrot_mul_i_ic_ic {
    Parrot_binop_i_ic_ic s!<op>!*! s/uicast/INTVAL/
}

Parrot_add_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/+/ s/uicast/INTVAL/
}

Parrot_sub_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/-/ s/uicast/INTVAL/
}

Parrot_cmod_i_ic_ic {
    Parrot_binop_i_ic_ic s!<op>!%! s/uicast/INTVAL/
}

Parrot_band_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/&/ s/uicast/INTVAL/
}

Parrot_bor_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/|/ s/uicast/INTVAL/
}

Parrot_bxor_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/^/ s/uicast/INTVAL/
}

Parrot_shl_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/<</ s/uicast/INTVAL/
}

Parrot_shr_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/>>/ s/uicast/INTVAL/
}

Parrot_lsr_i_ic_ic {
    Parrot_binop_i_ic_ic s/<op>/>>/ s/uicast/UINTVAL/
}

TEMPLATE Parrot_binop_n_nc_nc {
    if (MAP[1]) {
        jit_emit_mov_ri_n(interp, NATIVECODE, MAP[1], &NUM_CONST[2]);
        jit_emit_<op>_ri_n(interp, NATIVECODE, MAP[1], &NUM_CONST[3]);
    }
    else {
        jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &NUM_CONST[2]);
        jit_emit_<op>_ri_n(interp, NATIVECODE, FSR1, &NUM_CONST[3]);
        jit_emit_mov_MR_n(interp, NATIVECODE, ROFFS_NUM(1), FSR1)
    }
}

Parrot_add_n_nc_nc {
    Parrot_binop_n_nc_nc s/<op>/add/
}

Parrot_sub_n_nc_nc {
    Parrot_binop_n_nc_nc s/<op>/sub/
}

Parrot_mul_n_nc_nc {
    Parrot_binop_n_nc_nc s/<op>/mul/
}

Parrot_cmod_n_nc_nc {
    Parrot_binop_n_nc_nc s/<op>/cmod/
}

TEMPLATE Parrot_binop_x_x_xc {
    if (MAP[1] && MAP[2]) {
        if (*CUR_OPCODE == PARROT_OP_add_i_i_ic) {
            emitm_lea_m_r(interp, NATIVECODE, MAP(1), MAP(2), 0, 1, CUR_OPCODE[3]);
        }
        else if (*CUR_OPCODE == PARROT_OP_sub_i_i_ic) {
            emitm_lea_m_r(interp, NATIVECODE, MAP(1), MAP(2), 0, 1, -CUR_OPCODE[3]);
        }
        else {
            jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
            jit_emit_<op>_ri<_N>(interp, NATIVECODE, MAP[1], <typ>_CONST[3]);
        }
    }
    else if (MAP[1]) {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
        jit_emit_<op>_ri<_N>(interp, NATIVECODE, MAP[1], <typ>_CONST[3]);
    }
    else {
        if (MAP[2]) {
            jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
        }
        else {
            jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        }
        jit_emit_<op>_ri<_N>(interp, NATIVECODE, ISR1, <typ>_CONST[3]);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1)
    }
}

TEMPLATE Parrot_divop_x_x_xc {
    if (MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
    }
    jit_emit_<op>_ri<_N>(NATIVECODE, ISR1, <typ>_CONST[3]);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_add_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/add/ s/<typ>/*INT/
}

Parrot_add_n_n_nc {
    Parrot_binop_x_x_xc s/<_N>/_n/ s/<op>/add/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_sub_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/sub/ s/<typ>/*INT/
}

Parrot_sub_n_n_nc {
    Parrot_binop_x_x_xc s/<_N>/_n/ s/<op>/sub/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_div_i_i_ic {
    Parrot_divop_x_x_xc s/<_N>/_i/ s/<op>/div/ s/<typ>/*INT/
}

Parrot_mul_n_n_nc {
    Parrot_binop_x_x_xc s/<_N>/_n/ s/<op>/mul/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_div_n_n_nc {
    Parrot_binop_x_x_xc s/<_N>/_n/ s/<op>/div/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_cmod_i_i_ic {
    Parrot_divop_x_x_xc s/<_N>/_i/ s/<op>/cmod/ s/<typ>/*INT/
}

Parrot_cmod_n_n_nc {
    Parrot_binop_x_x_xc s/<_N>/_n/ s/<op>/cmod/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_bor_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/bor/ s/<typ>/*INT/
}

Parrot_bxor_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/bxor/ s/<typ>/*INT/
}

Parrot_band_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/band/ s/<typ>/*INT/
}

Parrot_shl_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/shl/ s/<typ>/*INT/
}

Parrot_shr_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/shr/ s/<typ>/*INT/
}

Parrot_lsr_i_i_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/lsr/ s/<typ>/*INT/
}

Parrot_rot_i_i_ic_ic {
    Parrot_binop_x_x_xc s/<_N>/_i/ s/<op>/rol/ s/<typ>/*INT/
}

TEMPLATE Parrot_binop_x_xc_x {
    if (MAP[1] && MAP[3]) {
        if (*CUR_OPCODE == PARROT_OP_add_i_ic_i) {
            emitm_lea_m_r(interp, NATIVECODE, MAP(1), MAP(3), 0, 1, CUR_OPCODE[2]);
        }
#ifdef emitm_f<op>
        else if (*CUR_OPCODE == PARROT_OP_<op>_n_nc_n && *&NUM_CONST[2] == 1.0) {
            emitm_fld1(NATIVECODE);
            emitm_f<op>(NATIVECODE, (MAP[3]+1));
            emitm_fstp(NATIVECODE, (MAP[1]+1));
        }
#endif
        else {
            if (MAP[1] == MAP[3]) {
                jit_emit_mov_ri<_N>(interp, NATIVECODE, ISR1, <typ>_CONST[2]);
                jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
                jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1)
            }
            else {
                jit_emit_mov_ri<_N>(interp, NATIVECODE, MAP[1], <typ>_CONST[2]);
                jit_emit_<op>_rr<_N>(interp, NATIVECODE, MAP[1], MAP[3]);
            }
        }
    }
    else if (MAP[1]) {
        jit_emit_mov_ri<_N>(interp, NATIVECODE, MAP[1], <typ>_CONST[2]);
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(3));
    }
    else if (MAP[3]) {
        jit_emit_mov_ri<_N>(interp, NATIVECODE, ISR1, <typ>_CONST[2]);
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1)
    }
    else {
        jit_emit_mov_ri<_N>(interp, NATIVECODE, ISR1, <typ>_CONST[2]);
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(3));
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_add_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/add/ s/<typ>/*INT/
}

Parrot_add_n_nc_n {
    Parrot_binop_x_xc_x s/<_N>/_n/ s/<op>/add/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_sub_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/sub/ s/<typ>/*INT/
}

Parrot_sub_n_nc_n {
    Parrot_binop_x_xc_x s/<_N>/_n/ s/<op>/sub/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_mul_n_nc_n {
    Parrot_binop_x_xc_x s/<_N>/_n/ s/<op>/mul/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_div_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/div/ s/<typ>/*INT/
}

Parrot_div_n_nc_n {
    Parrot_binop_x_xc_x s/<_N>/_n/ s/<op>/div/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_cmod_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/cmod/ s/<typ>/*INT/
}

Parrot_cmod_n_nc_n {
    Parrot_binop_x_xc_x s/<_N>/_n/ s/<op>/cmod/ s/INT/NUM/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_bor_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/bor/ s/<typ>/*INT/
}

Parrot_bxor_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/bxor/ s/<typ>/*INT/
}

Parrot_band_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/band/ s/<typ>/*INT/
}

Parrot_shl_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/shl/ s/<typ>/*INT/
}

Parrot_shr_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/shr/ s/<typ>/*INT/
}

Parrot_lsr_i_ic_i {
    Parrot_binop_x_xc_x s/<_N>/_i/ s/<op>/lsr/ s/<typ>/*INT/
}



TEMPLATE Parrot_binop_x_x_x {
    if (MAP[1] && MAP[2] && MAP[3]) {
        if (MAP[1] == MAP[3]) {
            jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
            jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
            jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
        }
        else {
            jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
            jit_emit_<op>_rr<_N>(interp, NATIVECODE, MAP[1], MAP[3]);
        }
    }
    else if (MAP[1] && MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(3));
    }
    else if (MAP[1] && MAP[3]) {
        if (MAP[1] == MAP[3]) {
            jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
            jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
            jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
        }
        else {
            jit_emit_mov_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
            jit_emit_<op>_rr<_N>(interp, NATIVECODE, MAP[1], MAP[3]);
        }
    }
    else if (MAP[2] && MAP[3]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
    else if (MAP[1]) {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(3));
    }
    else if (MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(3));
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
    else if (MAP[3]) {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(3));
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

TEMPLATE Parrot_divop_x_x_x {
    if (MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
    }
    if (MAP[3]) {
        jit_emit_<op>_rr<_N>(interp, NATIVECODE, ISR1, MAP[3]);
    }
    else {
        jit_emit_<op>_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(3));
    }
    if (MAP[1]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_mul_i_i_i {
        Parrot_binop_x_x_x s/<op>/mul/ s/<_N>/_i/
}

Parrot_add_i_i_i {
        Parrot_binop_x_x_x s/<op>/add/ s/<_N>/_i/
}

Parrot_sub_i_i_i {
        Parrot_binop_x_x_x s/<op>/sub/ s/<_N>/_i/
}

Parrot_div_i_i_i {
        Parrot_divop_x_x_x s/<op>/div/ s/<_N>/_i/
}

Parrot_bor_i_i_i {
        Parrot_binop_x_x_x s/<op>/bor/ s/<_N>/_i/
}

Parrot_bxor_i_i_i {
        Parrot_binop_x_x_x s/<op>/bxor/ s/<_N>/_i/
}

Parrot_band_i_i_i {
        Parrot_binop_x_x_x s/<op>/band/ s/<_N>/_i/
}

Parrot_shl_i_i_i {
        Parrot_binop_x_x_x s/<op>/shl/ s/<_N>/_i/
}

Parrot_shr_i_i_i {
        Parrot_binop_x_x_x s/<op>/shr/ s/<_N>/_i/
}

Parrot_lsr_i_i_i {
        Parrot_binop_x_x_x s/<op>/lsr/ s/<_N>/_i/
}

Parrot_cmod_i_i_i {
        Parrot_divop_x_x_x s/<op>/cmod/ s/<_N>/_i/
}

Parrot_sub_n_n_n {
        Parrot_binop_x_x_x s/<op>/sub/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_add_n_n_n {
        Parrot_binop_x_x_x s/<op>/add/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_mul_n_n_n {
        Parrot_binop_x_x_x s/<op>/mul/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_div_n_n_n {
        Parrot_binop_x_x_x s/<op>/div/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_cmod_n_n_n {
        Parrot_binop_x_x_x s/<op>/cmod/ s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/
}

TEMPLATE unary_x {
    if (MAP[1]) {
        jit_emit_<op>_r<_N>(NATIVECODE, MAP[1]);
    }
    else {
#ifdef jit_emit_<op>_M<_N>
        jit_emit_<op>_M<_N>(interp, NATIVECODE, ROFFS_INT(1));
#else
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(1));
        jit_emit_<op>_r<_N>(NATIVECODE, ISR1);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
#endif
    }
}

Parrot_neg_i {
    unary_x s/<_N>/_i/  s/<op>/neg/
}

Parrot_neg_n {
    unary_x s/<_N>/_n/ s/INT/NUM/  s/<op>/neg/
}


Parrot_bnot_i {
    unary_x s/<_N>/_i/  s/<op>/not/
}

Parrot_abs_i {
    unary_x s/<_N>/_i/ s/<op>/abs/
}

Parrot_abs_n {
    unary_x s/<_N>/_n/ s/INT/NUM/  s/<op>/abs/
}

TEMPLATE unary_x_x {
    if (MAP[1] && MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
        jit_emit_<op>_r<_N>(NATIVECODE, MAP[1]);
    }
    else if (MAP[1]) {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_INT(2));
        jit_emit_<op>_r<_N>(NATIVECODE, MAP[1]);
    }
    else if (MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
        jit_emit_<op>_r<_N>(NATIVECODE, ISR1);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(2));
        jit_emit_<op>_r<_N>(NATIVECODE, ISR1);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_bnot_i_i {
    unary_x_x s/<_N>/_i/ s/<op>/not/
}

Parrot_neg_i_i {
    unary_x_x s/<_N>/_i/ s/<op>/neg/
}

Parrot_abs_i_i {
    unary_x_x s/<_N>/_i/ s/<op>/abs/
}
Parrot_neg_n_n {
    unary_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/ s/<op>/neg/
}

Parrot_abs_n_n {
    unary_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/ s/<op>/abs/
}

Parrot_sin_n_n {
    unary_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/ s/<op>/sin/
}

Parrot_cos_n_n {
    unary_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/ s/<op>/cos/
}

Parrot_sqrt_n_n {
    unary_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT/NUM/ s/<op>/sqrt/
}


TEMPLATE Parrot_ifunless_x_ic {
    if ( P_ARITH && jit_info->prev_op[1] == jit_info->cur_op[1]) {
        jit_emit_jcc(jit_info, <jnz>, *INT_CONST[2]);
    }
    else if (MAP[1]) {
        jit_emit_test_r<_N>(NATIVECODE, MAP[1]);
        jit_emit_jcc(jit_info, <jne>, *INT_CONST[2]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_<t>(1));
        jit_emit_test_r<_N>(NATIVECODE, ISR1);
        jit_emit_jcc(jit_info, <jne>, *INT_CONST[2]);
    }
}

Parrot_if_i_ic {
    Parrot_ifunless_x_ic s/<jnz>/emitm_jnz/ s/<jne>/emitm_jne/ s/<_N>/_i/ s/<t>/INT/
}

Parrot_unless_i_ic {
    Parrot_ifunless_x_ic s/<jnz>/emitm_jz/ s/<jne>/emitm_je/ s/<_N>/_i/ s/<t>/INT/
}

Parrot_if_n_ic {
    Parrot_ifunless_x_ic s/<jnz>/emitm_jnz/ s/<jne>/emitm_jnz/ s/<_N>/_n/ s/<t>/NUM/ s/ISR/FSR/ s/P_ARITH/0/
}

Parrot_unless_n_ic {
    Parrot_ifunless_x_ic s/<jnz>/emitm_jz/ s/<jne>/emitm_jz/ s/<_N>/_n/ s/<t>/NUM/ s/ISR/FSR/ s/P_ARITH/0/
}

TEMPLATE Parrot_cmp_x_xc_ic {
    if (MAP[1]) {
        jit_emit_cmp_ri<_N>(interp, NATIVECODE, MAP[1], <c>_CONST[2]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_<t>(1));
        jit_emit_cmp_ri<_N>(interp, NATIVECODE, ISR1, <c>_CONST[2]);
    }
    jit_emit_jcc(jit_info, <je>, *INT_CONST[3]);
}

Parrot_eq_i_ic_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_i/ s/<je>/emitm_je/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_eq_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_je/ s/<t>/NUM/ s/<c>/&NUM/ s/ISR/FSR/
}

Parrot_ne_i_ic_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_i/ s/<je>/emitm_jne/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_ne_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jne/ s/<t>/NUM/ s/<c>/&NUM/ s/ISR/FSR/
}

Parrot_lt_i_ic_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_i/ s/<je>/emitm_jl/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_lt_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jb/ s/<t>/NUM/ s/<c>/&NUM/ s/ISR/FSR/
}

Parrot_le_i_ic_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_i/ s/<je>/emitm_jle/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_le_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jbe/ s/<c>/&NUM/ s/ISR/FSR/ s/<t>/NUM/
}

TEMPLATE Parrot_cmp_xc_x_ic {
    jit_emit_mov_ri<_N>(interp, NATIVECODE, ISR1,<c>_CONST[1]);
    if (MAP[2]) {
        jit_emit_cmp_rr<_N>(NATIVECODE, ISR1, MAP[2]);
    }
    else {
        jit_emit_cmp_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_<t>(2));
    }
    jit_emit_jcc(jit_info, <je>, *INT_CONST[3]);
}

Parrot_eq_ic_i_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_i/ s/<je>/emitm_je/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_eq_nc_n_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_n/ s/<je>/emitm_je/ s/<c>/&NUM/ s/ISR/FSR/ s/<t>/NUM/
}

Parrot_ne_ic_i_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_i/ s/<je>/emitm_jne/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_ne_nc_n_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_n/ s/<je>/emitm_jne/ s/<c>/&NUM/ s/ISR/FSR/ s/<t>/NUM/
}

Parrot_lt_ic_i_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_i/ s/<je>/emitm_jl/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_lt_nc_n_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_n/ s/<je>/emitm_jb/ s/<c>/&NUM/ s/ISR/FSR/ s/<t>/NUM/
}

Parrot_le_ic_i_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_i/ s/<je>/emitm_jle/ s/<c>/*INT/ s/<t>/INT/
}

Parrot_le_nc_n_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_n/ s/<je>/emitm_jbe/ s/<c>/&NUM/ s/ISR/FSR/ s/<t>/NUM/
}

TEMPLATE Parrot_cmp_x_x_ic {
    if (MAP[1] && MAP[2]) {
        jit_emit_cmp_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        jit_emit_cmp_RM<_N>(interp, NATIVECODE, MAP[1], ROFFS_<typ>(2));
    }
    else if (MAP[2]) {
        jit_emit_cmp_MR<_N>(interp, NATIVECODE, ROFFS_<typ>(1), MAP[2]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_<typ>(1));
        jit_emit_cmp_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_<typ>(2));
    }
    jit_emit_jcc(jit_info, <je>, *INT_CONST[3]);
}

Parrot_eq_i_i_ic {
    Parrot_cmp_x_x_ic s/<_N>/_i/ s/<je>/emitm_je/ s/<typ>/INT/
}

Parrot_eq_n_n_ic {
    Parrot_cmp_x_x_ic s/<_N>/_n/ s/<je>/emitm_je/ s/<typ>/NUM/ s/ISR/FSR/
}

Parrot_ne_i_i_ic {
    Parrot_cmp_x_x_ic s/<_N>/_i/ s/<je>/emitm_jne/ s/<typ>/INT/
}

Parrot_ne_n_n_ic {
    Parrot_cmp_x_x_ic s/<_N>/_n/ s/<je>/emitm_jne/ s/<typ>/NUM/ s/ISR/FSR/
}

Parrot_lt_i_i_ic {
    Parrot_cmp_x_x_ic s/<_N>/_i/ s/<je>/emitm_jl/ s/<typ>/INT/
}

Parrot_lt_n_n_ic {
    Parrot_cmp_x_x_ic s/<_N>/_n/ s/<je>/emitm_jb/ s/<typ>/NUM/ s/ISR/FSR/
}

Parrot_le_i_i_ic {
    Parrot_cmp_x_x_ic s/<_N>/_i/ s/<je>/emitm_jle/ s/<typ>/INT/
}

Parrot_le_n_n_ic {
    Parrot_cmp_x_x_ic s/<_N>/_n/ s/<je>/emitm_jbe/ s/<typ>/NUM/ s/ISR/FSR/
}

Parrot_branch_ic {
    emit_jump(jit_info, *INT_CONST[1]);
}

TEMPLATE Parrot_incdec_x {
    if (MAP[1]) {
        jit_emit_<op>_r<_N>(NATIVECODE, MAP[1]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, ISR1, ROFFS_INT(1));
        jit_emit_<op>_r<_N>(NATIVECODE, ISR1);
        jit_emit_mov_MR<_N>(interp, NATIVECODE, ROFFS_INT(1), ISR1)
    }
}

Parrot_inc_i {
    Parrot_incdec_x s/<op>/inc/ s/<_N>/_i/
}

Parrot_dec_i {
    Parrot_incdec_x s/<op>/dec/ s/<_N>/_i/
}

Parrot_inc_n {
    Parrot_incdec_x s/<op>/inc/ s/<_N>/_n/ s/INT/NUM/ s/ISR/FSR/
}

Parrot_dec_n {
    Parrot_incdec_x s/<op>/dec/ s/<_N>/_n/ s/INT/NUM/ s/ISR/FSR/
}


; string funcs
;
Parrot_set_s_sc {
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
    emitm_pushl_i(NATIVECODE, CONST(2)->u.string);
    emitm_pushl_r(NATIVECODE, emit_ECX);
    CALL_FUNCTION(jit_info, string_copy);
    emitm_addb_i_r(NATIVECODE, 8, emit_ESP);
    jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_STR(1), emit_EAX );
}

TEMPLATE Parrot_cmp_sx_sx_ic {
# define push_r(i) \
    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EAX, ROFFS_STR(i)); \
    emitm_pushl_r(NATIVECODE, emit_EAX)
# define push_c(i) emitm_pushl_i(NATIVECODE, CONST(i)->u.string)

    push_<typ2>(2);
    push_<typ1>(1);
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
    emitm_pushl_r(NATIVECODE, emit_ECX);
    CALL_FUNCTION(jit_info, string_compare);
    emitm_addb_i_r(NATIVECODE, 12, emit_ESP);
    jit_emit_test_r_i(NATIVECODE, emit_EAX);
    jit_emit_jcc(jit_info, <op>, *INT_CONST[3]);
#undef push_r
#undef push_c
}

TEMPLATE Parrot_eq_sx_sx_ic {
# define push_r(i) \
    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EAX, ROFFS_STR(i)); \
    emitm_pushl_r(NATIVECODE, emit_EAX)
# define push_c(i) emitm_pushl_i(NATIVECODE, CONST(i)->u.string)
    push_<typ2>(2);
    push_<typ1>(1);
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
    emitm_pushl_r(NATIVECODE, emit_ECX);
    CALL_FUNCTION(jit_info, string_equal);
    emitm_addb_i_r(NATIVECODE, 12, emit_ESP);
    jit_emit_test_r_i(NATIVECODE, emit_EAX);
    jit_emit_jcc(jit_info, <op>, *INT_CONST[3]);
#undef push_r
#undef push_c
}

Parrot_eq_s_s_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/r/ s/<typ2>/r/ s/<op>/emitm_jz/
}

Parrot_eq_s_sc_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/r/ s/<typ2>/c/ s/<op>/emitm_jz/
}

Parrot_eq_sc_s_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/c/ s/<typ2>/r/ s/<op>/emitm_jz/
}

Parrot_ne_s_s_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/r/ s/<typ2>/r/ s/<op>/emitm_jnz/
}

Parrot_ne_s_sc_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/r/ s/<typ2>/c/ s/<op>/emitm_jnz/
}

Parrot_ne_sc_s_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/c/ s/<typ2>/r/ s/<op>/emitm_jnz/
}

Parrot_le_s_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/r/ s/<op>/emitm_jle/
}

Parrot_le_s_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/c/ s/<op>/emitm_jle/
}

Parrot_le_sc_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/r/ s/<op>/emitm_jle/
}

Parrot_lt_s_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/r/ s/<op>/emitm_jl/
}

Parrot_lt_s_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/c/ s/<op>/emitm_jl/
}

Parrot_lt_sc_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/r/ s/<op>/emitm_jl/
}


TEMPLATE Parrot_ifunless_sx_ic {
# define push_r(i) \
    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EAX, ROFFS_STR(i)); \
    emitm_pushl_r(NATIVECODE, emit_EAX)
# define push_c(i) emitm_pushl_i(NATIVECODE, CONST(i)->u.string)

    push_<typ>(1);
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
    emitm_pushl_r(NATIVECODE, emit_ECX);
    CALL_FUNCTION(jit_info, string_bool);
    emitm_addb_i_r(NATIVECODE, 8, emit_ESP);
    jit_emit_test_r_i(NATIVECODE, emit_EAX);
    jit_emit_jcc(jit_info, <op>, *INT_CONST[2]);

#undef push_r
#undef push_c
}


Parrot_if_s_ic {
    Parrot_ifunless_sx_ic s/<typ>/r/ s/<op>/emitm_jnz/
}

Parrot_unless_s_ic {
    Parrot_ifunless_sx_ic s/<typ>/r/ s/<op>/emitm_jz/
}

TEMPLATE Parrot_ord_i_sx {
# define push_r(i) \
    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EAX, ROFFS_STR(i)); \
        emitm_pushl_r(NATIVECODE, emit_EAX)
# define push_c(i) emitm_pushl_i(NATIVECODE, CONST(i)->u.string)

    emitm_pushl_i(NATIVECODE, 0);
    push_<typ>(2);
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
    emitm_pushl_r(NATIVECODE, emit_ECX);
    CALL_FUNCTION(jit_info, string_ord);
    emitm_addb_i_r(NATIVECODE, 12, emit_ESP);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
#undef push_r
#undef push_c
}

Parrot_ord_i_s {
    Parrot_ord_i_sx s/<typ>/r/
}

Parrot_ord_i_sc {
    Parrot_ord_i_sx s/<typ>/c/
}

TEMPLATE Parrot_ord_i_sx_i {
# define push_r(i) \
    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EAX, ROFFS_STR(i)); \
        emitm_pushl_r(NATIVECODE, emit_EAX)
# define push_c(i) emitm_pushl_i(NATIVECODE, CONST(i)->u.string)

    if (MAP[3]) {
        emitm_pushl_r(NATIVECODE, MAP[3]);
    }
    else {
        jit_emit_mov_RM_i(interp, NATIVECODE, ISR1, ROFFS_INT(3));
        emitm_pushl_r(NATIVECODE, ISR1);
    }
    push_<typ>(2);
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_EAX);
    emitm_pushl_r(NATIVECODE, emit_EAX);
    CALL_FUNCTION(jit_info, string_ord);
    emitm_addb_i_r(NATIVECODE, 12, emit_ESP);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
#undef push_r
#undef push_c
}

Parrot_ord_i_s_i {
    char *L1, *L2, *L3, *L4, *L5, *Lpos, *L3a;
    /*
     * this opcode has a CALL_FUNCTION, so ext_call = -1
     * in src/jit.cpu.c for such ext_call types volatile
     * registers are stored back to Parrot registers: ecx, edx are usable
     */

    /*
     * movl $2, %ecx         # %ecx := string
     * movl $3, %edx         # %edx := offset
     * movl %ecx, %eax       # %eax := string_length
     * cmpl #0, %ecx
     * je  L1
     */
    jit_emit_mov_RM_i(interp, NATIVECODE, emit_ECX, ROFFS_STR(2));
    if (MAP[3]) {
        jit_emit_mov_rr_i(NATIVECODE, emit_EDX, MAP(3));
    }
    else {
        jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDX, ROFFS_INT(3));
    }
    jit_emit_mov_rr_i(NATIVECODE, emit_EAX, emit_ECX);
    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ECX, 0);
    L1 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jz, 0);
    /*
     * mov (strlen)%ecx, %eax
     */
    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_ECX, emit_None, 1,
            offsetof(STRING, strlen));
    /* L1: */
    L1[1] = (char)(NATIVECODE - L1 - 2);
    /*
     * cmpl #0, %eax
     * je  L2
     */
    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_EAX, 0);
    L2 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jz, 0);
    /*
     * cmp $edx, 0
     * jge Lpos
     * add %eax, %edx
     * js  L3a
     * Lpos:
     * cmp %edx, %eax
     * jge L3
     */
    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_EDX, 0);
    Lpos = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jnl, 0);
    jit_emit_add_rr_i(interp, NATIVECODE, emit_EDX, emit_EAX);
    L3a = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_js, 0);
    /* LPos: */
    Lpos[1] = (char)(NATIVECODE - Lpos - 2);

    jit_emit_cmp_rr_i(NATIVECODE, emit_EDX, emit_EAX);
    L3 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jnl, 0);

    /*
     * mov (encoding)%ecx, %eax
     * cmp fixed8, %ecx
     * jne L4
     */
    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_ECX, emit_None, 1,
            offsetof(STRING, encoding));
    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_EAX, Parrot_fixed_8_encoding_ptr);
    L4 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jnz, 0);
    /*
     * mov (strstart)%ecx, %ecx
     * xor %eax, %eax
     * movb (%ecx + %edx), %eax)
     */
    emitm_movl_m_r(interp, NATIVECODE, emit_ECX, emit_ECX, emit_None, 1,
            offsetof(STRING, strstart));
    jit_emit_bxor_rr_i(interp, NATIVECODE, emit_EAX, emit_EAX);
    emitm_movb_m_r(interp, NATIVECODE, emit_EAX, emit_ECX, emit_EDX, 1, 0);
    /*
     * branch L5
     */
    L5 = NATIVECODE;
    emitm_jumps(NATIVECODE, 0);

    L3a[1] = (char)(NATIVECODE - L3a - 2);
    /*
     * L3a:
     */
    jit_emit_sub_rr_i(interp, NATIVECODE, emit_EDX, emit_EAX);

    /*
     * L2:
     * L3:
     * L4:
     */
    L2[1] = (char)(NATIVECODE - L2 - 2);
    L3[1] = (char)(NATIVECODE - L3 - 2);
    L4[1] = (char)(NATIVECODE - L4 - 2);
    emitm_pushl_r(NATIVECODE, emit_EDX);        /* offs */
    emitm_pushl_r(NATIVECODE, emit_ECX);        /* string */
    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_EAX);
    emitm_pushl_r(NATIVECODE, emit_EAX);        /* interp */
    CALL_FUNCTION(jit_info, string_ord);
    emitm_addb_i_r(NATIVECODE, 12, emit_ESP);   /* result in eax */
    /*
     * L5:
     */
    L5[1] = (char)(NATIVECODE - L5 - 2);
    if (MAP[1] && MAP[1] != emit_ECX && MAP[1] != emit_EDX) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], emit_EAX);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), emit_EAX);
    }

}

Parrot_ord_i_sc_i {
    Parrot_ord_i_sx_i s/<typ>/c/
}

; the following 4 ops don't branch but are translated as cpfp
; which adds unneeded overhead - convert to normal ops
; or just JIT the 2 easy ones
Parrot_set_args_pc {
    if (jit_info->code_type == JIT_CODE_FILE) {
        Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_EAX);
        emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
                offsetof(Interp, current_args));
    }
    else  {
        jit_set_args_pc(jit_info, interp,
            jit_info->flags & JIT_CODE_RECURSIVE);
    }
}

extern Parrot_set_returns_pc {
    if (jit_info->code_type == JIT_CODE_FILE)
        Parrot_jit_normal_op(jit_info, interp);
    else  {
        jit_set_returns_pc(jit_info, interp,
            jit_info->flags & JIT_CODE_RECURSIVE);
    }
}

extern Parrot_returncc {
    if (jit_info->code_type == JIT_CODE_FILE)
        Parrot_jit_restart_op(jit_info, interp);
    else {
        /* restore pushed regs if any */
        if (!(jit_info->flags & JIT_CODE_RECURSIVE)) {
            jit_restore_regs(jit_info, interp);
            /* no branch ret 0 */
            jit_emit_bxor_rr_i(interp, NATIVECODE, emit_EAX, emit_EAX);
            jit_emit_stack_frame_leave(NATIVECODE);
        }
        emitm_ret(NATIVECODE);
    }
}

Parrot_pic_callr___pc {
    int offset, here, op_i;
    PackFile_Constant ** constants;
    PMC *sig_params, *sig_result;
    opcode_t *params;
    int skip;

    constants = CONTEXT(interp)->constants;
    params = jit_info->optimizer->sections->begin;
    sig_params = constants[params[1]]->u.key;
    op_i = 2 + SIG_ELEMS(sig_params);

    offset = jit_info->arena.op_map[op_i].offset;
    /* TODO preserve necessary regs */
    assert(*CUR_OPCODE == PARROT_OP_get_results_pc);
    constants = CONTEXT(interp)->constants;
    sig_result = constants[CUR_OPCODE[1]]->u.key;
    if (!SIG_ELEMS(sig_result))
        skip = -1;
    else
        skip = MAP(2);      /* skip result - save rest */
    /* registers are saved in set_args */

    here = NATIVECODE - jit_info->arena.start;
    emitm_calll(NATIVECODE, offset - here - 5);

    jit_restore_regs_call(jit_info, interp, skip);
}

extern Parrot_get_params_pc {
    if (jit_info->code_type == JIT_CODE_FILE)
        Parrot_jit_normal_op(jit_info, interp);
    else if (!(jit_info->flags & JIT_CODE_RECURSIVE)) {
        jit_get_params_pc(jit_info, interp);
    }
}

Parrot_get_results_pc {
    if (jit_info->code_type == JIT_CODE_FILE) {
        Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_EAX);
        emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_None, 1,
                offsetof(Interp, ctx.state));
        emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
                offsetof(Parrot_Context, current_results));
    }
    else {
        PackFile_Constant ** constants;
        PMC *sig_result;

        constants = CONTEXT(interp)->constants;
        sig_result = constants[CUR_OPCODE[1]]->u.key;
        if (!SIG_ELEMS(sig_result))
            return;
        if (SIG_ITEM(sig_result, 0) == PARROT_ARG_FLOATVAL) {
            /* float result is in ISR1 */
            emitm_fst(NATIVECODE, MAP(2));
        }
        else {
            jit_emit_mov_rr_i(NATIVECODE, MAP(2), emit_EAX);
        }
    }
}
; TODO or,and,not,cmp

TEMPLATE iscc_i_x_x {
    if (MAP[2] && MAP[3]) {
        jit_emit_cmp_rr<_N>(NATIVECODE, MAP[2], MAP[3]);
    }
    else if (MAP[2]) {
        jit_emit_cmp_RM<_N>(interp, NATIVECODE, MAP[2], ROFFS_<typ>(3));
    }
    else if (MAP[3]) {
        jit_emit_cmp_MR<_N>(interp, NATIVECODE, ROFFS_<typ>(2), MAP[3]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, <scr>, ROFFS_<typ>(2));
        jit_emit_cmp_RM<_N>(interp, NATIVECODE, <scr>, ROFFS_<typ>(3));
    }
    jit_emit_mov_ri_i(interp, NATIVECODE, ISR1, 0);
    jit_emit_setcc_r(NATIVECODE, <cc>, ISR1);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_iseq_i_i_i {
    iscc_i_x_x s/<_N>/_i/ s/<cc>/emitm_je/ s/<typ>/INT/ s/<scr>/ISR1/
}

Parrot_isne_i_i_i {
    iscc_i_x_x s/<_N>/_i/ s/<cc>/emitm_jne/ s/<typ>/INT/ s/<scr>/ISR1/
}

Parrot_islt_i_i_i {
    iscc_i_x_x s/<_N>/_i/ s/<cc>/emitm_jl/ s/<typ>/INT/ s/<scr>/ISR1/
}

Parrot_isle_i_i_i {
    iscc_i_x_x s/<_N>/_i/ s/<cc>/emitm_jle/ s/<typ>/INT/ s/<scr>/ISR1/
}

Parrot_iseq_i_n_n {
    iscc_i_x_x s/<_N>/_n/ s/<cc>/emitm_je/ s/<typ>/NUM/ s/<scr>/FSR1/
}

Parrot_isne_i_n_n {
    iscc_i_x_x s/<_N>/_n/ s/<cc>/emitm_jne/ s/<typ>/NUM/ s/<scr>/FSR1/
}

Parrot_islt_i_n_n {
    iscc_i_x_x s/<_N>/_n/ s/<cc>/emitm_jb/ s/<typ>/NUM/ s/<scr>/FSR1/
}

Parrot_isle_i_n_n {
    iscc_i_x_x s/<_N>/_n/ s/<cc>/emitm_jbe/ s/<typ>/NUM/ s/<scr>/FSR1/
}

TEMPLATE iscc_i_x_xc {
    if (MAP[2]) {
        jit_emit_cmp_ri<_N>(interp, NATIVECODE, MAP[2], <c>_CONST[3]);
    }
    else {
        jit_emit_mov_RM<_N>(interp, NATIVECODE, <scr>, ROFFS_<typ>(2));
        jit_emit_cmp_ri<_N>(interp, NATIVECODE, <scr>, <c>_CONST[3]);
    }
    jit_emit_mov_ri_i(interp, NATIVECODE, ISR1, 0);
    jit_emit_setcc_r(NATIVECODE, <cc>, ISR1);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_iseq_i_i_ic {
    iscc_i_x_xc s/<_N>/_i/ s/<cc>/emitm_je/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_isne_i_i_ic {
    iscc_i_x_xc s/<_N>/_i/ s/<cc>/emitm_jne/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_islt_i_i_ic {
    iscc_i_x_xc s/<_N>/_i/ s/<cc>/emitm_jl/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_isle_i_i_ic {
    iscc_i_x_xc s/<_N>/_i/ s/<cc>/emitm_jle/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_iseq_i_n_nc {
    iscc_i_x_xc s/<_N>/_n/ s/<cc>/emitm_je/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

Parrot_isne_i_n_nc {
    iscc_i_x_xc s/<_N>/_n/ s/<cc>/emitm_jne/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

Parrot_islt_i_n_nc {
    iscc_i_x_xc s/<_N>/_n/ s/<cc>/emitm_jb/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

Parrot_isle_i_n_nc {
    iscc_i_x_xc s/<_N>/_n/ s/<cc>/emitm_jbe/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

TEMPLATE iscc_i_xc_x {
    jit_emit_mov_ri<_N>(interp, NATIVECODE, <scr>, <c>_CONST[2]);
    if (MAP[3]) {
        jit_emit_cmp_rr<_N>(NATIVECODE, <scr>, MAP[3]);
    }
    else {
        jit_emit_cmp_RM<_N>(interp, NATIVECODE, <scr>, ROFFS_<typ>(3));
    }
    jit_emit_mov_ri_i(interp, NATIVECODE, ISR1, 0);
    jit_emit_setcc_r(NATIVECODE, <cc>, ISR1);
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_MR_i(interp, NATIVECODE, ROFFS_INT(1), ISR1);
    }
}

Parrot_iseq_i_ic_i {
    iscc_i_xc_x s/<_N>/_i/ s/<cc>/emitm_je/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_isne_i_ic_i {
    iscc_i_xc_x s/<_N>/_i/ s/<cc>/emitm_jne/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_islt_i_ic_i {
    iscc_i_xc_x s/<_N>/_i/ s/<cc>/emitm_jl/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_isle_i_ic_i {
    iscc_i_xc_x s/<_N>/_i/ s/<cc>/emitm_jle/ s/<typ>/INT/ s/<scr>/ISR1/ s/<c>/*INT/
}

Parrot_iseq_i_nc_n {
    iscc_i_xc_x s/<_N>/_n/ s/<cc>/emitm_je/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

Parrot_isne_i_nc_n {
    iscc_i_xc_x s/<_N>/_n/ s/<cc>/emitm_jne/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

Parrot_islt_i_nc_n {
    iscc_i_xc_x s/<_N>/_n/ s/<cc>/emitm_jb/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

Parrot_isle_i_nc_n {
    iscc_i_xc_x s/<_N>/_n/ s/<cc>/emitm_jbe/ s/<typ>/NUM/ s/<scr>/FSR1/ s/<c>/&NUM/
}

;
; TODO check alignment, and maybe move 1 msk into reg
;
Parrot_pow_n_n_i {
    int saved = 0;
    char *L1, *L2, *L3, *L4, *L5, *L6;

    emitm_fld1(NATIVECODE);              /* res = 1.0  ST(1) */
    if (MAP[3]) {
        jit_emit_mov_rr_i(NATIVECODE, emit_EAX, MAP[3]);
    }
    else {
        jit_emit_mov_RM_i(interp, NATIVECODE, emit_EAX, ROFFS_INT(3));
    }
    jit_emit_test_r_i(NATIVECODE, emit_EAX);               /* e == 0? */
    L1 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jz, 0);                    /* jz L1 */
    if (MAP[2]) {
        emitm_fld(NATIVECODE, (MAP[2] + 1));
    }
    else {
        jit_emit_fload_mb_n(interp, NATIVECODE, emit_EBX, ROFFS_NUM(2));
    }                                    /* n2  = $2   ST(0) */
    if (intreg_is_used(jit_info, emit_ECX)) {
        emitm_pushl_r(NATIVECODE, emit_ECX);
        saved = 1;
    }
    jit_emit_mov_ri_i(interp, NATIVECODE, emit_ECX, 1);    /* s = 1 */
    L2 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jg, 0);                    /* jg L2 */
    jit_emit_neg_r_i(NATIVECODE, emit_ECX);                /* s = -1 */
    jit_emit_neg_r_i(NATIVECODE, emit_EAX);                /* e = -e */
    L2[1] = NATIVECODE - L2 - 2;
    /* L2:  */
    /* while (e) */
        jit_emit_test_r_i(NATIVECODE, emit_EAX);            /* e == 0? */
        L4 = NATIVECODE;
        emitm_jxs(NATIVECODE, emitm_jz, 0);                 /* jz L4 */
        L3 = NATIVECODE;
        /* L3: */
        jit_emit_test_ri_i(NATIVECODE, emit_EAX, 1);        /* e & 1 ? */
        L5 = NATIVECODE;
        emitm_jxs(NATIVECODE, emitm_jz, 0);                 /* jz L5 */
        jit_emit_mul_rr_n(interp, NATIVECODE, 1, 0);        /* res *= n2 */
        /* L5: */
        L5[1] = (char)(NATIVECODE - L5 - 2);
        jit_emit_lsr_ri_i(interp, NATIVECODE, emit_EAX, 1);  /* e >>= 1 */
        jit_emit_mul_rr_n(interp, NATIVECODE, 0, 0);         /* n2 *= n2 */
        /* lsr is setting flags - branch past test at L3 */
        emitm_jxs(NATIVECODE, emitm_jnz, (L3 - NATIVECODE - 1)); /* jmp L3 */
    /* endwhile */
    L4[1] = (char)(NATIVECODE - L4 - 2);
    /* L4:  */
    jit_emit_test_r_i(NATIVECODE, emit_ECX);               /* s ? */
    L6 = NATIVECODE;
    emitm_jxs(NATIVECODE, emitm_jg, 0);                    /* jg L6 */
    emitm_fld1(NATIVECODE);                                /* push 1.0 */
    emitm_fxch(NATIVECODE, 2);
    emitm_fdivp(NATIVECODE, 2);                            /* res = 1.0/res */
    L6[1] = (char)(NATIVECODE - L6 - 2);
    /* L6:  */
    emitm_fstp(NATIVECODE, 0);                             /* pop n2 */
    L1[1] = (char)(NATIVECODE - L1 - 2);
    /* L1:  */
    if (MAP[1]) {
        emitm_fstp(NATIVECODE, (MAP[1] + 1));              /* store res */
    }
    else {
        jit_emit_fstore_m_n(interp, NATIVECODE, ROFFS_NUM(1));
    }
    if (saved)
        emitm_popl_r(NATIVECODE, emit_ECX);
}

/*
 * Local variables:
 * c-indentation-style: bsd
 * c-basic-offset: 4
 * indent-tabs-mode: nil
 * End:
 *
 * vim: expandtab shiftwidth=4:
 */
