The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
;
; i386/core.jit
;
; $Id: core.jit,v 1.55 2004/04/28 21:39:59 leo Exp $
;

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

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>(NATIVECODE, MAP[1], &INT_REG[2]);
    }
    else if (MAP[2]) {
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], MAP[2]);
    }
    else {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1);
    }
}

Parrot_set_n_n {
    Parrot_set_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

Parrot_set_p_p {
    Parrot_set_x_x s/<_N>/_i/ s/INT_R/PMC_R/
}

Parrot_set_s_s {
    Parrot_set_x_x s/<_N>/_i/ s/INT_R/STRING_R/
}

TEMPLATE Parrot_set_x_ic {
    if (MAP[1]) {
        jit_emit_mov_ri<_N>(NATIVECODE, MAP[1], <typ>_CONST[2]);
    }
    else {
        jit_emit_mov_mi<_N>(NATIVECODE, &INT_REG[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/<typ>/&INT/ s/INT_R/NUM_R/
}

Parrot_set_n_nc {
    if (MAP[1]) {
        jit_emit_mov_rm_n(NATIVECODE, MAP[1], &NUM_CONST[2]);
    }
    else {
        jit_emit_mov_rm_n(NATIVECODE, FSR1, &NUM_CONST[2]);
        jit_emit_mov_mr_n(NATIVECODE, &NUM_REG[1], FSR1);
    }
}

Parrot_set_n_i {
; store mapped int
    if (MAP[2]) {
        jit_emit_mov_mr_i(NATIVECODE, &INT_REG[2], MAP[2]);
    }
    if (MAP[1]) {
        jit_emit_mov_ri_ni(NATIVECODE, MAP[1], &INT_REG[2]);
    }
    else {
        jit_emit_mov_ri_ni(NATIVECODE, FSR1, &INT_REG[2]);
        jit_emit_mov_mr_n(NATIVECODE, &NUM_REG[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, &INT_REG[1], MAP[2]);
;    }
;    else {
;        jit_emit_mov_rm_n(NATIVECODE, FSR1, &NUM_REG[2]);
;        jit_emit_mov_mr_in(NATIVECODE, &INT_REG[1], FSR1);
;    }
;    if (MAP[1]) {
;        jit_emit_mov_rm_i(NATIVECODE, MAP[1], &INT_REG[1]);
;    }
;}
;
;Parrot_set_i_nc {
;    jit_emit_mov_rm_n(NATIVECODE, FSR1, &NUM_CONST[2]);
;    jit_emit_mov_mr_in(NATIVECODE, &INT_REG[1], FSR1);
;    if (MAP[1]) {
;        jit_emit_mov_rm_i(NATIVECODE, MAP[1], &INT_REG[1]);
;    }
;}

; -- null op.
TEMPLATE Parrot_null_x {
    if (MAP[1]) {
        jit_emit_mov_ri<_N>(NATIVECODE, MAP[1], <val>);
    }
    else {
        jit_emit_mov_mi<_N>(NATIVECODE, &INT_REG[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_R/PMC_R/ s/<val>/PMCNULL/
}

Parrot_null_s {
    Parrot_null_x s/<_N>/_i/ s/INT_R/STRING_R/ s/<val>/NULL/
}

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

TEMPLATE Parrot_binop_x_x {
    if (MAP[1] && MAP[2]) {
        jit_emit_<op>_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        jit_emit_<op>_rm<_N>(NATIVECODE, MAP[1], &INT_REG[2]);
    }
    else if (MAP[2]) {
# ifdef jit_emit_<op>_mr<_N>
        jit_emit_<op>_mr<_N>(NATIVECODE, &INT_REG[1], MAP[2]);
# else
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[1]);
        jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[2]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1);
# endif
    }
    else {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[1]);
        jit_emit_<op>_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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>(NATIVECODE, ISR1, &INT_REG[1]);
    }
    if (MAP[2]) {
        jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[2]);
    }
    else {
        jit_emit_<op>_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
    }
    if (MAP[1]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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_R/NUM_R/
}

Parrot_add_n_n {
    Parrot_binop_x_x s/<op>/add/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_sub_n_n {
    Parrot_binop_x_x s/<op>/sub/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_div_n_n {
    Parrot_binop_x_x s/<op>/div/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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_R/STRING_R/
}

Parrot_exchange_p_p {
    Parrot_binop_x_x s/<op>/xchg/ s/<_N>/_i/ s/INT_R/PMC_R/
}

Parrot_exchange_n_n {
    Parrot_binop_x_x s/<op>/xchg/ s/<_N>/_n/ s/INT_R/NUM_R/
}

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], &INT_REG[2]);
    }
    else if (MAP[2]) {
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[3], MAP[2]);
        jit_emit_mov_mr_i(NATIVECODE, &INT_REG[1], ISR1);
    }
    else {
        jit_emit_mov_rm_i(NATIVECODE, ISR1, &INT_REG[2]);
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[3], ISR1);
        jit_emit_mov_mr_i(NATIVECODE, &INT_REG[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], &INT_REG[3]);
    }
    else if (MAP[3]) {
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[2], MAP[3]);
        jit_emit_mov_mr_i(NATIVECODE, &INT_REG[1], ISR1);
    }
    else {
        jit_emit_mov_rm_i(NATIVECODE, ISR1, &INT_REG[3]);
        jit_emit_mul_rir_i(NATIVECODE, ISR1, *INT_CONST[2], ISR1);
        jit_emit_mov_mr_i(NATIVECODE, &INT_REG[1], ISR1);
    }
}

TEMPLATE Parrot_binop_x_xc {
    if (MAP[1]) {
        jit_emit_<op>_ri<_N>(NATIVECODE, MAP[1], <typ>_CONST[2]);
    }
    else {
# ifdef jit_emit_<op>_mi_<_N>
        jit_emit_<op>_mi<_N>(NATIVECODE, &INT_REG[1], <typ>_CONST[2]);
# else
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[1]);
        jit_emit_<op>_ri<_N>(NATIVECODE, ISR1, <typ>_CONST[2]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1)
# endif
    }
}

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

Parrot_mul_i_ic {
    Parrot_binop_x_xc s/<_N>/_i/ s/<op>/mul/ s/<typ>/*INT/
}

Parrot_div_i_ic {
    if (MAP[1]) {
        jit_emit_mov_rr_i(NATIVECODE, ISR1, MAP[1]);
    }
    else {
        jit_emit_mov_rm_i(NATIVECODE, ISR1, &INT_REG[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(NATIVECODE, &INT_REG[1], ISR1);
    }
}

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

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

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

TEMPLATE Parrot_binop_i_ic_ic {
    if (MAP[1]) {
        jit_emit_mov_ri_i(NATIVECODE, MAP[1], (INTVAL)((uicast)*INT_CONST[2] <op> *INT_CONST[3]));
    }
    else {
        jit_emit_mov_mi_i(NATIVECODE, &INT_REG[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_div_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(NATIVECODE, MAP[1], &NUM_CONST[2]);
        jit_emit_<op>_ri_n(NATIVECODE, MAP[1], &NUM_CONST[3]);
    }
    else {
        jit_emit_mov_ri_n(NATIVECODE, FSR1, &NUM_CONST[2]);
        jit_emit_<op>_ri_n(NATIVECODE, FSR1, &NUM_CONST[3]);
        jit_emit_mov_mr_n(NATIVECODE, &NUM_REG[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_div_n_nc_nc {
    Parrot_binop_n_nc_nc s/<op>/div/
}

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

TEMPLATE Parrot_binop_x_x_xc {
    if (MAP[1] && MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], MAP[2]);
        jit_emit_<op>_ri<_N>(NATIVECODE, MAP[1], <typ>_CONST[3]);
    }
    else if (MAP[1]) {
        jit_emit_mov_rm<_N>(NATIVECODE, MAP[1], &INT_REG[2]);
        jit_emit_<op>_ri<_N>(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>(NATIVECODE, ISR1, &INT_REG[2]);
        }
        jit_emit_<op>_ri<_N>(NATIVECODE, ISR1, <typ>_CONST[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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>(NATIVECODE, ISR1, &INT_REG[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(NATIVECODE, &INT_REG[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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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/
}

TEMPLATE Parrot_binop_x_xc_x {
    if (MAP[1] && MAP[3]) {
        if (MAP[1] == MAP[3]) {
            jit_emit_mov_ri<_N>(NATIVECODE, ISR1, <typ>_CONST[2]);
            jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[3]);
            jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1)
        }
        else {
            jit_emit_mov_ri<_N>(NATIVECODE, MAP[1], <typ>_CONST[2]);
            jit_emit_<op>_rr<_N>(NATIVECODE, MAP[1], MAP[3]);
        }
    }
    else if (MAP[1]) {
        jit_emit_mov_ri<_N>(NATIVECODE, MAP[1], <typ>_CONST[2]);
        jit_emit_<op>_rm<_N>(NATIVECODE, MAP[1], &INT_REG[3]);
    }
    else if (MAP[3]) {
        jit_emit_mov_ri<_N>(NATIVECODE, ISR1, <typ>_CONST[2]);
        jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1)
    }
    else {
        jit_emit_mov_ri<_N>(NATIVECODE, ISR1, <typ>_CONST[2]);
        jit_emit_<op>_rm<_N>(NATIVECODE, ISR1, &INT_REG[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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>(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>(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>(NATIVECODE, MAP[1], &INT_REG[3]);
    }
    else if (MAP[1] && MAP[3]) {
        if (MAP[1] == MAP[3]) {
            jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
            jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[3]);
            jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
        }
        else {
            jit_emit_mov_rm<_N>(NATIVECODE, MAP[1], &INT_REG[2]);
            jit_emit_<op>_rr<_N>(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>(NATIVECODE, ISR1, MAP[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1);
    }
    else if (MAP[1]) {
        jit_emit_mov_rm<_N>(NATIVECODE, MAP[1], &INT_REG[2]);
        jit_emit_<op>_rm<_N>(NATIVECODE, MAP[1], &INT_REG[3]);
    }
    else if (MAP[2]) {
        jit_emit_mov_rr<_N>(NATIVECODE, ISR1, MAP[2]);
        jit_emit_<op>_rm<_N>(NATIVECODE, ISR1, &INT_REG[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1);
    }
    else if (MAP[3]) {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
        jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1);
    }
    else {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
        jit_emit_<op>_rm<_N>(NATIVECODE, ISR1, &INT_REG[3]);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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>(NATIVECODE, ISR1, &INT_REG[2]);
    }
    if (MAP[3]) {
        jit_emit_<op>_rr<_N>(NATIVECODE, ISR1, MAP[3]);
    }
    else {
        jit_emit_<op>_rm<_N>(NATIVECODE, ISR1, &INT_REG[3]);
    }
    if (MAP[1]) {
        jit_emit_mov_rr<_N>(NATIVECODE, MAP[1], ISR1);
    }
    else {
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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_R/NUM_R/
}

Parrot_add_n_n_n {
        Parrot_binop_x_x_x s/<op>/add/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_mul_n_n_n {
        Parrot_binop_x_x_x s/<op>/mul/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_div_n_n_n {
        Parrot_binop_x_x_x s/<op>/div/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_cmod_n_n_n {
        Parrot_binop_x_x_x s/<op>/cmod/ s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/
}

TEMPLATE Parrot_neg_x {
    if (MAP[1]) {
        jit_emit_neg_r<_N>(NATIVECODE, MAP[1]);
    }
    else {
        jit_emit_neg_m<_N>(NATIVECODE, &INT_REG[1]);
    }
}

Parrot_neg_i {
    Parrot_neg_x s/<_N>/_i/
}

Parrot_neg_n {
    Parrot_neg_x s/<_N>/_n/ s/INT_R/NUM_R/
}

Parrot_neg_i_ic {
    if (MAP[1]) {
        jit_emit_mov_ri_i(NATIVECODE, MAP[1], -(*INT_CONST[2]));
    }
    else {
        jit_emit_mov_mi_i(NATIVECODE, &INT_REG[1], -(*INT_CONST[2]));
    }
}

Parrot_abs_i_ic {
    INTVAL i = *INT_CONST[2];
    if (MAP[1]) {
        jit_emit_mov_ri_i(NATIVECODE, MAP[1], i < 0 ? -i : i);
    }
    else {
        jit_emit_mov_mi_i(NATIVECODE, &INT_REG[1], i < 0 ? -i : i);
    }
}

TEMPLATE Parrot_absneg_n_nc {
    if (MAP[1]) {
        jit_emit_mov_rm_n(NATIVECODE, MAP[1], &NUM_CONST[2]);
        jit_emit_<op>_r_n(NATIVECODE, MAP[1]);
    }
    else {
        jit_emit_mov_rm_n(NATIVECODE, FSR1, &NUM_CONST[2]);
        jit_emit_<op>_r_n(NATIVECODE, FSR1);
        jit_emit_mov_mr_n(NATIVECODE, &NUM_REG[1], FSR1);
    }
}

Parrot_neg_n_nc {
    Parrot_absneg_n_nc s/<op>/neg/
}

Parrot_abs_n_nc {
    Parrot_absneg_n_nc s/<op>/abs/
}

TEMPLATE Parrot_absneg_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>(NATIVECODE, MAP[1], &INT_REG[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>(NATIVECODE, &INT_REG[1], ISR1);
    }
    else {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[2]);
        jit_emit_<op>_r<_N>(NATIVECODE, ISR1);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[1], ISR1);
    }
}

Parrot_bnot_i_i {
    Parrot_absneg_x_x s/<_N>/_i/ s/<op>/not/
}
Parrot_bnot_i_ic {
    if (MAP[1]) {
        jit_emit_mov_ri_i(NATIVECODE, MAP[1], ~(*INT_CONST[2]));
    }
    else {
        jit_emit_mov_mi_i(NATIVECODE, &INT_REG[1], ~(*INT_CONST[2]));
    }
}

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

Parrot_abs_i_i {
    Parrot_absneg_x_x s/<_N>/_i/ s/<op>/abs/
}
Parrot_neg_n_n {
    Parrot_absneg_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/ s/<op>/neg/
}

Parrot_abs_n_n {
    Parrot_absneg_x_x s/<_N>/_n/ s/ISR/FSR/ s/INT_R/NUM_R/ s/<op>/abs/
}

TEMPLATE Parrot_ifunless_xc_ic {
    if (*<x>_CONST[1] <op> 0)
        emit_jump(jit_info, *INT_CONST[2]);
}

Parrot_if_ic_ic {
    Parrot_ifunless_xc_ic s/<op>/!=/ s/<x>/INT/
}

Parrot_unless_ic_ic {
    Parrot_ifunless_xc_ic s/<op>/==/ s/<x>/INT/
}

Parrot_if_nc_ic {
    Parrot_ifunless_xc_ic s/<op>/!=/ s/<x>/NUM/
}

Parrot_unless_nc_ic {
    Parrot_ifunless_xc_ic s/<op>/==/ s/<x>/NUM/
}

TEMPLATE Parrot_ifunless_x_ic {
 /*
  * FIXME
  * dec I1
  * inc I0
  * if I1, boom
  */
    if (P_ARITH) {
        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>(NATIVECODE, ISR1, &INT_REG[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/
}

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

Parrot_if_n_ic {
    Parrot_ifunless_x_ic s/<jnz>/emitm_jnz/ s/<jne>/emitm_jnz/ s/<_N>/_n/ s/INT_R/NUM_R/ 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/INT_R/NUM_R/ s/ISR/FSR/ s/P_ARITH/0/
}

TEMPLATE Parrot_cmp_x_xc_ic {
    if (MAP[1]) {
        jit_emit_cmp_ri<_N>(NATIVECODE, MAP[1], <typ>_CONST[2]);
    }
    else {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, &INT_REG[1]);
        jit_emit_cmp_ri<_N>(NATIVECODE, ISR1, <typ>_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/<typ>/*INT/
}

Parrot_eq_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_je/ s/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

Parrot_ne_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jne/ s/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_gt_i_ic_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_i/ s/<je>/emitm_jg/ s/<typ>/*INT/
}

Parrot_gt_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_ja/ s/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

Parrot_ge_i_ic_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_i/ s/<je>/emitm_jnl/ s/<typ>/*INT/
}

Parrot_ge_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jnb/ s/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

Parrot_lt_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jb/ s/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

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

Parrot_le_n_nc_ic {
    Parrot_cmp_x_xc_ic s/<_N>/_n/ s/<je>/emitm_jbe/ s/<typ>/&NUM/ s/ISR/FSR/ s/INT_R/NUM_R/
}

TEMPLATE Parrot_cmp_xc_x_ic {
    jit_emit_mov_ri<_N>(NATIVECODE, ISR1,<typ>_CONST[1]);
    if (MAP[2]) {
        jit_emit_cmp_rr<_N>(NATIVECODE, ISR1, MAP[2]);
    }
    else {
        jit_emit_cmp_rm<_N>(NATIVECODE, ISR1, &INT_REG[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/<typ>/*INT/
}

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

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

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

Parrot_gt_ic_i_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_i/ s/<je>/emitm_jg/ s/<typ>/*INT/
}

Parrot_gt_nc_n_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_n/ s/<je>/emitm_ja/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_ge_ic_i_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_i/ s/<je>/emitm_jnl/ s/<typ>/*INT/
}

Parrot_ge_nc_n_ic {
    Parrot_cmp_xc_x_ic s/<_N>/_n/ s/<je>/emitm_jnb/ s/<typ>/&NUM/ s/ISR/FSR/
}

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

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

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

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

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>(NATIVECODE, MAP[1], <typ>_REG[2]);
    }
    else if (MAP[2]) {
        jit_emit_cmp_mr<_N>(NATIVECODE, <typ>_REG[1], MAP[2]);
    }
    else {
        jit_emit_mov_rm<_N>(NATIVECODE, ISR1, <typ>_REG[1]);
        jit_emit_cmp_rm<_N>(NATIVECODE, ISR1, <typ>_REG[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_gt_i_i_ic {
    Parrot_cmp_x_x_ic s/<_N>/_i/ s/<je>/emitm_jg/ s/<typ>/&INT/
}

Parrot_gt_n_n_ic {
    Parrot_cmp_x_x_ic s/<_N>/_n/ s/<je>/emitm_ja/ s/<typ>/&NUM/ s/ISR/FSR/
}

Parrot_ge_i_i_ic {
    Parrot_cmp_x_x_ic s/<_N>/_i/ s/<je>/emitm_jnl/ s/<typ>/&INT/
}

Parrot_ge_n_n_ic {
    Parrot_cmp_x_x_ic s/<_N>/_n/ s/<je>/emitm_jnb/ 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>(NATIVECODE, ISR1, &INT_REG[1]);
        jit_emit_<op>_r<_N>(NATIVECODE, ISR1);
        jit_emit_mov_mr<_N>(NATIVECODE, &INT_REG[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_R/NUM_R/ s/ISR/FSR/
}

Parrot_dec_n {
    Parrot_incdec_x s/<op>/dec/ s/<_N>/_n/ s/INT_R/NUM_R/ s/ISR/FSR/
}


TEMPLATE Parrot_cmp_xc_xc_ic {
    if (<typ>_CONST[1] <op> <typ>_CONST[2])
        emit_jump(jit_info, *INT_CONST[3]);
}

Parrot_lt_ic_ic_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*INT/ s/<op>/</
}

Parrot_lt_nc_nc_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*NUM/ s/<op>/</
}

Parrot_gt_ic_ic_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*INT/ s/<op>/>/
}

Parrot_gt_nc_nc_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*NUM/ s/<op>/>/
}

Parrot_ge_ic_ic_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*INT/ s/<op>/>=/
}

Parrot_ge_nc_nc_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*NUM/ s/<op>/>=/
}

Parrot_le_ic_ic_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*INT/ s/<op>/<=/
}

Parrot_le_nc_nc_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*NUM/ s/<op>/<=/
}

Parrot_eq_ic_ic_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*INT/ s/<op>/==/
}

Parrot_eq_nc_nc_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*NUM/ s/<op>/==/
}

Parrot_ne_ic_ic_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*INT/ s/<op>/!=/
}

Parrot_ne_nc_nc_ic {
    Parrot_cmp_xc_xc_ic s/<typ>/*NUM/ s/<op>/!=/
}

; string funcs
;
Parrot_set_s_sc {
    emitm_pushl_i(NATIVECODE, CONST(2)->u.string);
    emitm_pushl_i(NATIVECODE, interpreter);
#if 1
    call_func(jit_info, (void*) string_copy);
#else
; this works with 99% tests and break t/pmc/coroutine_3 ?why?
    emitm_calll(NATIVECODE, (char*)string_copy - NATIVECODE - 4);
#endif
    emitm_addb_i_r(NATIVECODE, 8, emit_ESP);
    jit_emit_mov_mr_i(NATIVECODE, &STRING_REG[1], emit_EAX );
}

TEMPLATE Parrot_cmp_sx_sx_ic {
# define push_r(i) \
    jit_emit_mov_rm_i(NATIVECODE, emit_EAX, &SREG(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);
    emitm_pushl_i(NATIVECODE, interpreter);
    call_func(jit_info, (void*)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(NATIVECODE, emit_EAX, &SREG(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);
    emitm_pushl_i(NATIVECODE, interpreter);
    call_func(jit_info, (void*)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_eq_sc_sc_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/c/ s/<typ2>/c/ 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_ne_sc_sc_ic {
    Parrot_eq_sx_sx_ic s/<typ1>/c/ s/<typ2>/c/ 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_le_sc_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/c/ 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/
}

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


Parrot_ge_s_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/r/ s/<op>/emitm_jnl/
}

Parrot_ge_s_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/c/ s/<op>/emitm_jnl/
}

Parrot_ge_sc_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/r/ s/<op>/emitm_jnl/
}

Parrot_ge_sc_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/c/ s/<op>/emitm_jnl/
}

Parrot_gt_s_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/r/ s/<op>/emitm_jg/
}

Parrot_gt_s_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/r/ s/<typ2>/c/ s/<op>/emitm_jg/
}

Parrot_gt_sc_s_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/r/ s/<op>/emitm_jg/
}

Parrot_gt_sc_sc_ic {
    Parrot_cmp_sx_sx_ic s/<typ1>/c/ s/<typ2>/c/ s/<op>/emitm_jg/
}


TEMPLATE Parrot_ifunless_sx_ic {
# define push_r(i) \
    jit_emit_mov_rm_i(NATIVECODE, emit_EAX, &SREG(i)); \
    emitm_pushl_r(NATIVECODE, emit_EAX)
# define push_c(i) emitm_pushl_i(NATIVECODE, CONST(i)->u.string)

    push_<typ>(1);
    emitm_pushl_i(NATIVECODE, interpreter);
    call_func(jit_info, (void*)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_if_sc_ic {
    Parrot_ifunless_sx_ic s/<typ>/c/ s/<op>/emitm_jnz/
}

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

Parrot_unless_sc_ic {
    Parrot_ifunless_sx_ic s/<typ>/c/ s/<op>/emitm_jz/
}

TEMPLATE Parrot_ord_i_sx {
# define push_r(i) \
    jit_emit_mov_rm_i(NATIVECODE, emit_EAX, &SREG(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);
    emitm_pushl_i(NATIVECODE, interpreter);
    call_func(jit_info, (void*)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(NATIVECODE, &INT_REG[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/
;}

; TODO or,and,not,cmp


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