;
; amd64/core.jit
;
; $Id: /mirror/trunk/src/jit/amd64/core.jit 20635 2007-08-15T18:40:31.863509Z jisom  $
;

Parrot_end {
    jit_emit_end(NATIVECODE);
}

Parrot_noop {
    emit_nop(NATIVECODE);
}

TEMPLATE Parrot_set_x_x {
    if (MAP[1] && MAP[2]) {
        emit_mov_<R>_<R>(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        emit_mov_<R>_m<R>(NATIVECODE, MAP[1], RBX, ROFFS_INT(2));
    }
    else if (MAP[2]) {
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), MAP[2]);
    }
    else {
        emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(2));
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
}


Parrot_set_i_i {
    Parrot_set_x_x s/<R>/r/
}

Parrot_set_i_ic {
    if (MAP[1]) {
        emit_mov_r_i(NATIVECODE, MAP[1], *INT_CONST[2]);
    }
    else {
        emit_mov_mr_i(NATIVECODE, RBX, (long)ROFFS_INT(1), *INT_CONST[2]);
    }
}

Parrot_set_n_n {
    Parrot_set_x_x s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_set_i_n {
    if (MAP[1] && MAP[2]) {
        emit_cvttsd2si_r_x(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        emit_cvttsd2si_r_mx(NATIVECODE, MAP[1], RBX, ROFFS_NUM(2));
    }
    else if (MAP[2]) {
        emit_cvttsd2si_r_x(NATIVECODE, ISR1, MAP[2]);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
    else {
        emit_cvttsd2si_r_mx(NATIVECODE, ISR1, RBX, ROFFS_NUM(2));
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
}

Parrot_set_i_nc {
    if (MAP[1]) {
        emit_xor_r_r(NATIVECODE, ISR1, ISR1);
        emit_cvttsd2si_r_mx(NATIVECODE, MAP[1], ISR1, &NUM_CONST[2]);
    }
    else {
        emit_xor_r_r(NATIVECODE, ISR1, ISR1);
        emit_cvttsd2si_r_mx(NATIVECODE, FSR1, ISR1, &NUM_CONST[2]);
        emit_mov_mx_x(NATIVECODE, RBX, ROFFS_NUM(1), FSR1);
    }
}

Parrot_set_n_i {
    if (MAP[1] && MAP[2]) {
        emit_cvtsi2sd_x_r(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        emit_cvtsi2sd_x_mr(NATIVECODE, MAP[1], RBX, ROFFS_INT(2));
    }
    else if (MAP[2]) {
        emit_cvtsi2sd_x_r(NATIVECODE, FSR1, MAP[2]);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_NUM(1), FSR1);
    }
    else {
        emit_cvtsi2sd_x_mr(NATIVECODE, FSR1, RBX, ROFFS_INT(2));
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_NUM(1), FSR1);
    }
}

Parrot_set_n_ic {
    if (MAP[1]) {
        emit_mov_r_i(NATIVECODE, ISR1, *INT_CONST[2]);
        emit_cvtsi2sd_x_r(NATIVECODE, MAP[1], ISR1);
    }
    else {
        emit_mov_r_i(NATIVECODE, ISR1, *INT_CONST[2]);
        emit_cvtsi2sd_x_r(NATIVECODE, FSR1, ISR1);
        emit_mov_mx_x(NATIVECODE, RBX, ROFFS_NUM(1), FSR1);
    }
}

Parrot_set_n_nc {
    if (MAP[1]) {
        /* I want something like this
         * emit_mov_x_mx(NATIVECODE, MAP[1], RBX, ROFFS_NUM(2));
         * but this works, even if ugly
         * It's either this or dereferencing
         *      ((interp->ctx).state)->constants[cur_opcode[2]]->u.number
         * Instead we do a jit-run time
         * &interp->code->const_table->constants[jit_info->cur_op[2]]->u.number
         */
        emit_xor_r_r(NATIVECODE, ISR1, ISR1);
        emit_mov_x_mx(NATIVECODE, MAP[1], ISR1, &NUM_CONST[2]);
    }
    else {
        /* unmapped floats is screwy at the moment, but we get 15 plus a
         * scratch */
        emit_xor_r_r(NATIVECODE, ISR1, ISR1);
        emit_mov_x_mx(NATIVECODE, FSR1, ISR1, &NUM_CONST[2]);
        emit_mov_mx_x(NATIVECODE, RBX, ROFFS_NUM(1), FSR1);
    }
}


TEMPLATE Parrot_binop_x_x {
    if (MAP[1] && MAP[2]) {
        emit_<op>_<R>_<R>(NATIVECODE, MAP[1], MAP[2]);
    }
    else if (MAP[1]) {
        emit_<op>_<R>_m<R>(NATIVECODE, MAP[1], RBX, ROFFS_INT(2));
    }
    else if (MAP[2]) {
# ifdef emit_<op>_m<R>_<R>
        emit_<op>_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), MAP[2]);
# else
        emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_<op>_<R>_<R>(NATIVECODE, ISR1, MAP[2]);
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
# endif
    }
    else {
        emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_<op>_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(2));
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
}

TEMPLATE Parrot_binop_x_xc {
    if (MAP[1]) {
        emit_<op>_<R>_i(NATIVECODE, MAP[1], *INT_CONST[2]);
    }
    else {
# ifdef emit_<op>_m<R>_i
        emit_<op>_m<R>_i(NATIVECODE, RBX, ROFFS_INT(1), *INT_CONST[2]);
# else
        emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_<op>_<R>_i(NATIVECODE, ISR1, *INT_CONST[2]);
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
# endif
    }
}

TEMPLATE Parrot_binop_x_x_x {
    if (MAP[1] && MAP[2] && MAP[3]){
        if (MAP[1] == MAP[3]) {
            emit_mov_<R>_<R>(NATIVECODE, ISR1, MAP[2]);
            emit_<op>_<R>_<R>(NATIVECODE, ISR1, MAP[3]);
            emit_mov_<R>_<R>(NATIVECODE, MAP[1], ISR1);
        }
        else {
            emit_mov_<R>_<R>(NATIVECODE, MAP[1], MAP[2]);
            emit_<op>_<R>_<R>(NATIVECODE, MAP[1], MAP[3]);
        }
    }
    else if (MAP[1] && MAP[2]) {
        emit_mov_<R>_<R>(NATIVECODE, MAP[1], MAP[2]);
        emit_<op>_<R>_m<R>(NATIVECODE, MAP[1], RBX, ROFFS_INT(3));
    }
    else if (MAP[1] && MAP[3]) {
        if (MAP[1] == MAP[3]) {
            emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(2));
            emit_<op>_<R>_<R>(NATIVECODE, ISR1, MAP[3]);
            emit_mov_<R>_<R>(NATIVECODE, MAP[1], ISR1);
        }
        else {
            emit_mov_<R>_m<R>(NATIVECODE, MAP[1], RBX, ROFFS_INT(2));
            emit_<op>_<R>_<R>(NATIVECODE, MAP[1], MAP[3]);
        }
    }
    else if (MAP[2] && MAP[3]) {
        emit_mov_<R>_<R>(NATIVECODE, ISR1, MAP[2]);
        emit_<op>_<R>_<R>(NATIVECODE, ISR1, MAP[3]);
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
    else if (MAP[1]) {
        emit_mov_<R>_m<R>(NATIVECODE, MAP[1], RBX, ROFFS_INT(2));
        emit_<op>_<R>_m<R>(NATIVECODE, MAP[1], RBX, ROFFS_INT(3));
    }
    else if (MAP[2]) {
        emit_mov_<R>_<R>(NATIVECODE, ISR1, MAP[2]);
        emit_<op>_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(3));
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
    else if (MAP[3]) {
        emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(2));
        emit_<op>_<R>_<R>(NATIVECODE, ISR1, MAP[3]);
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
    else {
        emit_mov_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(2));
        emit_<op>_<R>_m<R>(NATIVECODE, ISR1, RBX, ROFFS_INT(3));
        emit_mov_m<R>_<R>(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
}

Parrot_add_i_i {
    Parrot_binop_x_x s/<op>/add/ s/<R>/r/
}

Parrot_add_i_ic {
    Parrot_binop_x_xc s/<op>/add/ s/<R>/r/
}

Parrot_add_i_i_i {
    Parrot_binop_x_x_x s/<op>/add/ s/<R>/r/
}

Parrot_sub_i_i {
    Parrot_binop_x_x s/<op>/sub/ s/<R>/r/
}

Parrot_sub_i_ic {
    Parrot_binop_x_xc s/<op>/sub/ s/<R>/r/
}

Parrot_sub_i_i_i {
    Parrot_binop_x_x_x s/<op>/sub/ s/<R>/r/
}

Parrot_band_i_i {
    Parrot_binop_x_x s/<op>/and/ s/<R>/r/
}

Parrot_band_i_i_i {
    Parrot_binop_x_x_x s/<op>/and/ s/<R>/r/
}

Parrot_band_i_ic {
    Parrot_binop_x_xc s/<op>/and/ s/<R>/r/
}

Parrot_bxor_i_i {
    Parrot_binop_x_x s/<op>/xor/ s/<R>/r/
}

Parrot_bxor_i_ic {
    Parrot_binop_x_xc s/<op>/xor/ s/<R>/r/
}

Parrot_bxor_i_i_i {
    Parrot_binop_x_x_x s/<op>/xor/ s/<R>/r/
}

Parrot_bor_i_i {
    Parrot_binop_x_x s/<op>/or/ s/<R>/r/
}

Parrot_bor_i_ic {
    Parrot_binop_x_xc s/<op>/or/ s/<R>/r/
}

Parrot_bor_i_i_i {
    Parrot_binop_x_x_x s/<op>/or/ s/<R>/r/
}

Parrot_neg_i {
    if (MAP[1]) {
        emit_not_r(NATIVECODE, MAP[1]);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_neg_r(NATIVECODE, ISR1);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
}

Parrot_mul_i_i {
    Parrot_binop_x_x s/<op>/imul/ s/<R>/r/ s/ISR1/ISR2/
}       

Parrot_div_i_i {
    if (MAP[1]) {
        emit_mov_r_r(NATIVECODE, ISR2, MAP[1]);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR2, RBX, ROFFS_INT(1));
    }

    if (MAP[2]) {
        emit_idiv_r_r(NATIVECODE, ISR2, MAP[2]);
    }
    else {
        emit_idiv_r_mr(NATIVECODE, ISR2, RBX, ROFFS_INT(2));
    }

    if (MAP[2]) {
        emit_mov_r_r(NATIVECODE, MAP[1], ISR2);
    }
    else {
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_INT(1), ISR2);
    }
}



Parrot_not_i {
    if (MAP[1]) {
        emit_not_r(NATIVECODE, MAP[1]);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_not_r(NATIVECODE, ISR1);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_INT(1), ISR1);
    }
}

Parrot_exchange_i_i {
    Parrot_binop_x_x s/<op>/xchg/ s/<R>/r/
}

Parrot_exchange_s_s {
    Parrot_binop_x_x s/<op>/xchg/ s/<R>/r/ s/INT/STR/
}

Parrot_exchange_p_p {
    Parrot_binop_x_x s/<op>/xchg/ s/<R>/r/ s/INT/PMC/
}


TEMPLATE Parrot_unary_x {
    if (MAP[1]) {
        emit_<op>_r(NATIVECODE, MAP[1]);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_<op>_r(NATIVECODE, ISR1);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_INT(1), ISR1)
    }
}

Parrot_inc_i {
    Parrot_unary_x s/<op>/inc/
}

Parrot_dec_i {
    Parrot_unary_x s/<op>/dec/
}

Parrot_add_n_n {
    Parrot_binop_x_x s/<op>/add/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_add_n_n_n {
    Parrot_binop_x_x_x s/<op>/add/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_sub_n_n {
    Parrot_binop_x_x s/<op>/sub/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_sub_n_n_n {
    Parrot_binop_x_x_x s/<op>/sub/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_mul_n_n {
    Parrot_binop_x_x s/<op>/mul/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_mul_n_n_n {
    Parrot_binop_x_x_x s/<op>/mul/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_div_n_n {
    Parrot_binop_x_x s/<op>/div/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_div_n_n_n {
    Parrot_binop_x_x_x s/<op>/div/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}

Parrot_sqrt_n_n {
    Parrot_binop_x_x s/<op>/sqrt/ s/<R>/x/ s/ISR/FSR/ s/INT/NUM/
}


Parrot_neg_n {
    if (MAP[1]) {
        emit_mov_r_i(NATIVECODE, ISR1, 1L << 63);
        emit_movd_x_r(NATIVECODE, FSR1, ISR1);
        emit_xor_x_x(NATIVECODE, MAP[1], FSR1);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR1, RBX, ROFFS_NUM(1));
        emit_mov_r_i(NATIVECODE, RAX, 1L << 63);
        emit_xor_r_r(NATIVECODE, ISR1, RAX);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_NUM(1), ISR1);
    }
}

Parrot_abs_n {
    if (MAP[1]) {
        emit_mov_r_i(NATIVECODE, ISR1, ~(1L << 63));
        emit_movd_x_r(NATIVECODE, FSR1, ISR1);
        emit_and_x_x(NATIVECODE, MAP[1], FSR1);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR1, RBX, ROFFS_NUM(1));
        emit_mov_r_i(NATIVECODE, RAX, ~(1L << 63));
        emit_and_r_r(NATIVECODE, ISR1, RAX);
        emit_mov_mr_r(NATIVECODE, RBX, ROFFS_NUM(1), ISR1);
    }
}

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

TEMPLATE Parrot_ifunless_x_ic {
    if (MAP[1]) {
        emit_test_<R>(NATIVECODE, MAP[1]);
        emit_jcc_fixup(jit_info, <jcc>, *INT_CONST[2]);
    }
    else {
        emit_mov_r_mr(NATIVECODE, ISR1, RBX, ROFFS_INT(1));
        emit_test_<R>(NATIVECODE, ISR1);
        emit_jcc_fixup(jit_info, <jcc>, *INT_CONST[2]);
    }
}

Parrot_if_i_ic {
    Parrot_ifunless_x_ic s/<jcc>/jcc_jnz/ s/<R>/r/
}

Parrot_unless_i_ic {
    Parrot_ifunless_x_ic s/<jcc>/jcc_jz/ s/<R>/r/
}

Parrot_if_n_ic {
    Parrot_ifunless_x_ic s/<jcc>/jcc_jnz/ s/<R>/x/ s/ISR/FSR/
}

Parrot_unless_n_ic {
    Parrot_ifunless_x_ic s/<jcc>/jcc_jz/ s/<R>/x/ s/ISR/FSR/
}



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