Alien-TinyCCx
view release on metacpan or search on metacpan
src/arm-gen.c view on Meta::CPAN
if ((pplan->sval->type.t & VT_BTYPE) == VT_STRUCT) {
int padding = 0;
size = type_size(&pplan->sval->type, &align);
/* align to stack align size */
size = (size + 3) & ~3;
if (i == STACK_CLASS && pplan->prev)
padding = pplan->start - pplan->prev->end;
size += padding; /* Add padding if any */
/* allocate the necessary size on stack */
gadd_sp(-size);
/* generate structure store */
r = get_reg(RC_INT);
o(0xE28D0000|(intr(r)<<12)|padding); /* add r, sp, padding */
vset(&vtop->type, r | VT_LVAL, 0);
vswap();
vstore(); /* memcpy to current sp + potential padding */
/* Homogeneous float aggregate are loaded to VFP registers
immediately since there is no way of loading data in multiple
non consecutive VFP registers as what is done for other
structures (see the use of todo). */
if (i == VFP_STRUCT_CLASS) {
int first = pplan->start, nb = pplan->end - first + 1;
/* vpop.32 {pplan->start, ..., pplan->end} */
o(0xECBD0A00|(first&1)<<22|(first>>1)<<12|nb);
/* No need to write the register used to a SValue since VFP regs
cannot be used for gcall_or_jmp */
}
} else {
if (is_float(pplan->sval->type.t)) {
#ifdef TCC_ARM_VFP
r = vfpr(gv(RC_FLOAT)) << 12;
if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
size = 4;
else {
size = 8;
r |= 0x101; /* vpush.32 -> vpush.64 */
}
o(0xED2D0A01 + r); /* vpush */
#else
r = fpr(gv(RC_FLOAT)) << 12;
if ((pplan->sval->type.t & VT_BTYPE) == VT_FLOAT)
size = 4;
else if ((pplan->sval->type.t & VT_BTYPE) == VT_DOUBLE)
size = 8;
else
size = LDOUBLE_SIZE;
if (size == 12)
r |= 0x400000;
else if(size == 8)
r|=0x8000;
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]))
( run in 0.982 second using v1.01-cache-2.11-cpan-5b529ec07f3 )