Пример #1
0
static u32 regMipsToArmHelper(u32 regmips, u32 action, u32 type)
{
    int regnum = regcache.reglist[regcache.reglist_cnt];

    while( regnum != 0xFF )
    {
        if(regcache.arm[regnum].arm_type == REG_EMPTY)
        {
            break;
        }
        regcache.reglist_cnt++;
        regnum = regcache.reglist[regcache.reglist_cnt];
    }

    if( regnum == 0xFF )
    {
        regFreeRegs();
        regnum = regcache.reglist[regcache.reglist_cnt];
    }

    regcache.arm[regnum].arm_type = type;
    regcache.arm[regnum].arm_islocked = true;
    regcache.mips[regmips].mips_ischanged = false;

    if( action != REG_LOADBRANCH )
    {
        regcache.arm[regnum].arm_age = 0;
        regcache.arm[regnum].arm_use = 0;
        regcache.arm[regnum].ismapped = true;
        regcache.arm[regnum].mappedto = regmips;
        regcache.mips[regmips].ismapped = true;
        regcache.mips[regmips].mappedto = regnum;
    }
    else
    {
        regcache.arm[regnum].arm_age = 0;
        regcache.arm[regnum].arm_use = 0xFF;
        regcache.arm[regnum].ismapped = false;
        regcache.arm[regnum].mappedto = 0;
        if( regmips != 0 )
        {
            ARM_LDR_IMM(ARM_POINTER, regnum, PERM_REG_1, CalcDisp(regmips));
        }
        else
        {
            ARM_MOV_REG_IMM8(ARM_POINTER, regnum, 0);
        }

        regcache.reglist_cnt++;

        return regnum;
    }

    if(action == REG_LOAD)
    {
        if( regmips != 0 )
        {
            ARM_LDR_IMM(ARM_POINTER, regcache.mips[regmips].mappedto, PERM_REG_1, CalcDisp(regmips));
        }
        else
        {
            ARM_MOV_REG_IMM8(ARM_POINTER, regcache.mips[regmips].mappedto, 0);
        }
    }

    regcache.reglist_cnt++;

    return regnum;
}
Пример #2
0
/*
 * Returns a pointer to a native function that can be used to
 * call the specified method.
 * The function created will receive the arguments according
 * to the call convention specified in the method.
 * This function works by creating a MonoInvocation structure,
 * filling the fields in and calling ves_exec_method on it.
 * Still need to figure out how to handle the exception stuff
 * across the managed/unmanaged boundary.
 */
void* mono_arch_create_method_pointer (MonoMethod* method)
{
    MonoMethodSignature* sig;
    guchar* p, * p_method, * p_stackval_from_data, * p_exec;
    void* code_buff;
    int i, stack_size, arg_pos, arg_add, stackval_pos, offs;
    int areg, reg_args, shift, pos;
    MonoJitInfo *ji;

    code_buff = alloc_code_buff(128);
    p = (guchar*)code_buff;

    sig = method->signature;

    ARM_B(p, 3);

    /* embed magic number followed by method pointer */
    *p++ = 'M';
    *p++ = 'o';
    *p++ = 'n';
    *p++ = 'o';
    /* method ptr */
    *(void**)p = method;
    p_method = p;
    p += 4;

    /* call table */
    *(void**)p = stackval_from_data;
    p_stackval_from_data = p;
    p += 4;
    *(void**)p = ves_exec_method;
    p_exec = p;
    p += 4;

    stack_size = sizeof(MonoInvocation) + ARG_SIZE*(sig->param_count + 1) + ARM_NUM_ARG_REGS*2*sizeof(armword_t);

    /* prologue */
    p = (guchar*)arm_emit_lean_prologue((arminstr_t*)p, stack_size,
                                        (1 << ARMREG_R4) |
                                        (1 << ARMREG_R5) |
                                        (1 << ARMREG_R6) |
                                        (1 << ARMREG_R7));

    /* R7 - ptr to stack args */
    ARM_MOV_REG_REG(p, ARMREG_R7, ARMREG_IP);

    /*
     * Initialize MonoInvocation fields, first the ones known now.
     */
    ARM_MOV_REG_IMM8(p, ARMREG_R4, 0);
    ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(ex));
    ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(ex_handler));
    ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(parent));

    /* Set the method pointer. */
    ARM_LDR_IMM(p, ARMREG_R4, ARMREG_PC, -(int)(p - p_method + sizeof(arminstr_t)*2));
    ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(method));

    if (sig->hasthis) {
        /* [this] in A1 */
        ARM_STR_IMM(p, ARMREG_A1, ARMREG_SP, MINV_OFFS(obj));
    } else {
        /* else set minv.obj to NULL */
        ARM_STR_IMM(p, ARMREG_R4, ARMREG_SP, MINV_OFFS(obj));
    }

    /* copy args from registers to stack */
    areg = ARMREG_A1 + sig->hasthis;
    arg_pos = -(int)(ARM_NUM_ARG_REGS - sig->hasthis) * 2 * sizeof(armword_t);
    arg_add = 0;
    for (i = 0; i < sig->param_count; ++i) {
        if (areg >= ARM_NUM_ARG_REGS) break;
        ARM_STR_IMM(p, areg, ARMREG_R7, arg_pos);
        ++areg;
        if (!sig->params[i]->byref) {
            switch (sig->params[i]->type) {
            case MONO_TYPE_I8:
            case MONO_TYPE_U8:
            case MONO_TYPE_R8:
                if (areg >= ARM_NUM_ARG_REGS) {
                    /* load second half of 64-bit arg */
                    ARM_LDR_IMM(p, ARMREG_R4, ARMREG_R7, 0);
                    ARM_STR_IMM(p, ARMREG_R4, ARMREG_R7, arg_pos + sizeof(armword_t));
                    arg_add = sizeof(armword_t);
                } else {
                    /* second half is already the register */
                    ARM_STR_IMM(p, areg, ARMREG_R7, arg_pos + sizeof(armword_t));
                    ++areg;
                }
                break;
            case MONO_TYPE_VALUETYPE:
            /* assert */
            default:
                break;
            }
        }
        arg_pos += 2 * sizeof(armword_t);
    }
    /* number of args passed in registers */
    reg_args = i;



    /*
     * Calc and save stack args ptr,
     * args follow MonoInvocation struct on the stack.
     */
    ARM_ADD_REG_IMM8(p, ARMREG_R1, ARMREG_SP, sizeof(MonoInvocation));
    ARM_STR_IMM(p, ARMREG_R1, ARMREG_SP, MINV_OFFS(stack_args));

    /* convert method args to stackvals */
    arg_pos = -(int)(ARM_NUM_ARG_REGS - sig->hasthis) * 2 * sizeof(armword_t);
    stackval_pos = sizeof(MonoInvocation);
    for (i = 0; i < sig->param_count; ++i) {
        if (i < reg_args) {
            ARM_SUB_REG_IMM8(p, ARMREG_A3, ARMREG_R7, -arg_pos);
            arg_pos += 2 * sizeof(armword_t);
        } else {
            if (arg_pos < 0) arg_pos = 0;
            pos = arg_pos + arg_add;
            if (pos <= 0xFF) {
                ARM_ADD_REG_IMM8(p, ARMREG_A3, ARMREG_R7, pos);
            } else {
                if (is_arm_const((armword_t)pos)) {
                    shift = calc_arm_mov_const_shift((armword_t)pos);
                    ARM_ADD_REG_IMM(p, ARMREG_A3, ARMREG_R7, pos >> ((32 - shift) & 31), shift >> 1);
                } else {
                    p = (guchar*)arm_mov_reg_imm32((arminstr_t*)p, ARMREG_R6, (armword_t)pos);
                    ARM_ADD_REG_REG(p, ARMREG_A2, ARMREG_R7, ARMREG_R6);
                }
            }
            arg_pos += sizeof(armword_t);
            if (!sig->params[i]->byref) {
                switch (sig->params[i]->type) {
                case MONO_TYPE_I8:
                case MONO_TYPE_U8:
                case MONO_TYPE_R8:
                    arg_pos += sizeof(armword_t);
                    break;
                case MONO_TYPE_VALUETYPE:
                /* assert */
                default:
                    break;
                }
            }
        }