void emit_call_with_gp(Merced_Code_Emitter& emitter,
                       void **proc_ptr,
                       bool flushrs,
                       int saved_gp_reg)
{
    void *new_gp = proc_ptr[1];
    void *vm_gp = get_vm_gp_value();

    // Set the gp according to the IPF software conventions. 
    if (new_gp != vm_gp)
    {
        if (saved_gp_reg != 0)
            emitter.ipf_mov(saved_gp_reg, GP_REG);
        emit_mov_imm_compactor(emitter, GP_REG, (uint64)new_gp);
    }

    uint64 branch_target = (uint64)(*proc_ptr);

    emit_mov_imm_compactor(emitter, SCRATCH_GENERAL_REG, branch_target, 0);
    if (flushrs) {
        emitter.ipf_mtbr(BRANCH_CALL_REG, SCRATCH_GENERAL_REG);
        emit_mov_imm_compactor(emitter, SCRATCH_GENERAL_REG, (uint64)m2n_gen_flush_and_call(), 0);
    }
    emitter.ipf_mtbr(SCRATCH_BRANCH_REG, SCRATCH_GENERAL_REG);
    emitter.ipf_bricall(br_few, br_sptk, br_none, BRANCH_RETURN_LINK_REG, SCRATCH_BRANCH_REG);

    // Restore the saved GP.
    if (new_gp != vm_gp && saved_gp_reg != 0)
        emitter.ipf_mov(GP_REG, saved_gp_reg);
} //emit_call_with_gp
Example #2
0
void gen_vm_rt_athrow_internal_compactor(Merced_Code_Emitter &emitter)
{
    const int out_arg0 = m2n_gen_push_m2n(&emitter, NULL, FRAME_UNKNOWN, false, 0, 0, 4);
    m2n_gen_save_extra_preserved_registers(&emitter);
    emitter.ipf_mov(out_arg0+0,  IN_REG0);
    emitter.ipf_mov(out_arg0+1,  IN_REG1);
    emitter.ipf_mov(out_arg0+2,  0);
    emitter.ipf_mov(out_arg0+3,  0);
    emit_call_with_gp(emitter, (void **)exn_athrow, true, 5);
} //gen_vm_rt_athrow_internal_compactor
void emit_dealloc_for_single_call(Merced_Code_Emitter& emitter,
                                  int save_pfs_reg,
                                  int save_b0_reg,
                                  int save_gp_reg,
                                  int pred)
{
    if (save_gp_reg != 0)
        emitter.ipf_mov(GP_REG, save_gp_reg, pred);
    emitter.ipf_mtap(AR_pfs, save_pfs_reg, pred);
    emitter.ipf_mtbr(BRANCH_RETURN_LINK_REG, save_b0_reg, pred);
}
void emit_alloc_for_single_call(Merced_Code_Emitter& emitter,
                                int num_in_args,
                                int num_out_args,
                                void **function,
                                int& out0_reg,
                                int& save_pfs_reg,
                                int& save_b0_reg,
                                int& save_gp_reg)
{
    bool should_save_gp = (function[1] != get_vm_gp_value());
    int num_local = (should_save_gp ? 3 : 2);
    save_pfs_reg = IN_REG0 + num_in_args;
    save_b0_reg = save_pfs_reg + 1;
    save_gp_reg = (should_save_gp ? save_b0_reg + 1 : 0);
    out0_reg = IN_REG0 + num_in_args + num_local;
    emitter.ipf_alloc(save_pfs_reg, num_in_args, num_local, num_out_args, 0);
    emitter.ipf_mfbr(save_b0_reg, BRANCH_RETURN_LINK_REG);
    if (should_save_gp)
        emitter.ipf_mov(save_gp_reg, GP_REG);
}
void emit_branch_with_gp(Merced_Code_Emitter& emitter,
                         void **proc_ptr)
{
    void *new_gp = proc_ptr[1];
    void *vm_gp = get_vm_gp_value();

    // Set the gp according to the IPF software conventions. 
    if (new_gp != vm_gp)
    {
        emit_mov_imm_compactor(emitter, GP_REG, (uint64)new_gp);
    }

    uint64 branch_target = (uint64)(*proc_ptr);

    emit_mov_imm_compactor(emitter, SCRATCH_GENERAL_REG, branch_target, 0);
    emitter.ipf_mtbr(SCRATCH_BRANCH_REG, SCRATCH_GENERAL_REG);
    emitter.ipf_bri(br_cond, br_few, br_sptk, br_none, SCRATCH_BRANCH_REG);

    // someone else will restore the gp, according to the software conventions
} //emit_branch_with_gp