Alien-TinyCCx
view release on metacpan or search on metacpan
src/arm-gen.c view on Meta::CPAN
o(0xED2D0100|r|(size>>2)); /* some kind of vpush for FPA */
#endif
} else {
/* simple type (currently always same size) */
/* XXX: implicit cast ? */
size=4;
if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
lexpand_nr();
size = 8;
r = gv(RC_INT);
o(0xE52D0004|(intr(r)<<12)); /* push r */
vtop--;
}
r = gv(RC_INT);
o(0xE52D0004|(intr(r)<<12)); /* push r */
}
if (i == STACK_CLASS && pplan->prev)
gadd_sp(pplan->prev->end - pplan->start); /* Add padding if any */
}
break;
case VFP_CLASS:
gv(regmask(TREG_F0 + (pplan->start >> 1)));
if (pplan->start & 1) { /* Must be in upper part of double register */
o(0xEEF00A40|((pplan->start>>1)<<12)|(pplan->start>>1)); /* vmov.f32 s(n+1), sn */
vtop->r = VT_CONST; /* avoid being saved on stack by gv for next float */
}
break;
case CORE_CLASS:
if ((pplan->sval->type.t & VT_BTYPE) == VT_LLONG) {
lexpand_nr();
gv(regmask(pplan->end));
pplan->sval->r2 = vtop->r;
vtop--;
}
gv(regmask(pplan->start));
/* Mark register as used so that gcall_or_jmp use another one
(regs >=4 are free as never used to pass parameters) */
pplan->sval->r = vtop->r;
break;
}
vtop--;
}
}
/* second pass to restore registers that were saved on stack by accident.
Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */
if (++pass < 2)
goto again;
/* Manually free remaining registers since next parameters are loaded
* manually, without the help of gv(int). */
save_regs(nb_args);
if(todo) {
o(0xE8BD0000|todo); /* pop {todo} */
for(pplan = plan->clsplans[CORE_STRUCT_CLASS]; pplan; pplan = pplan->prev) {
int r;
pplan->sval->r = pplan->start;
/* An SValue can only pin 2 registers at best (r and r2) but a structure
can occupy more than 2 registers. Thus, we need to push on the value
stack some fake parameter to have on SValue for each registers used
by a structure (r2 is not used). */
for (r = pplan->start + 1; r <= pplan->end; r++) {
if (todo & (1 << r)) {
nb_extra_sval++;
vpushi(0);
vtop->r = r;
}
}
}
}
return nb_extra_sval;
}
/* Generate function call. The function address is pushed first, then
all the parameters in call order. This functions pops all the
parameters and the function address. */
void gfunc_call(int nb_args)
{
int r, args_size;
int def_float_abi = float_abi;
int todo;
struct plan plan;
#ifdef TCC_ARM_EABI
int variadic;
if (float_abi == ARM_HARD_FLOAT) {
variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS);
if (variadic || floats_in_core_regs(&vtop[-nb_args]))
float_abi = ARM_SOFTFP_FLOAT;
}
#endif
/* cannot let cpu flags if other instruction are generated. Also avoid leaving
VT_JMP anywhere except on the top of the stack because it would complicate
the code generator. */
r = vtop->r & VT_VALMASK;
if (r == VT_CMP || (r & ~1) == VT_JMP)
gv(RC_INT);
args_size = assign_regs(nb_args, float_abi, &plan, &todo);
#ifdef TCC_ARM_EABI
if (args_size & 7) { /* Stack must be 8 byte aligned at fct call for EABI */
args_size = (args_size + 7) & ~7;
o(0xE24DD004); /* sub sp, sp, #4 */
}
#endif
nb_args += copy_params(nb_args, &plan, todo);
tcc_free(plan.pplans);
/* Move fct SValue on top as required by gcall_or_jmp */
vrotb(nb_args + 1);
gcall_or_jmp(0);
if (args_size)
gadd_sp(args_size); /* pop all parameters passed on the stack */
#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
if(float_abi == ARM_SOFTFP_FLOAT && is_float(vtop->type.ref->type.t)) {
( run in 1.000 second using v1.01-cache-2.11-cpan-39bf76dae61 )