Alien-TinyCCx
view release on metacpan or search on metacpan
src/arm64-gen.c view on Meta::CPAN
// lab2:
write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2);
}
}
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
int *align, int *regsize)
{
return 0;
}
ST_FUNC void greturn(void)
{
CType *t = &func_vt;
unsigned long a;
arm64_pcs(0, &t, &a);
switch (a) {
case -1:
break;
case 0:
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
int align, size = type_size(&func_vt, &align);
gaddrof();
gv(RC_R(0));
arm64_ldrs(0, size);
}
else
gv(RC_IRET);
break;
case 1: {
CType type = func_vt;
mk_pointer(&type);
vset(&type, VT_LOCAL | VT_LVAL, func_vc);
indir();
vswap();
vstore();
break;
}
case 16:
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
gaddrof();
gv(RC_R(0));
for (j = 0; j < n; j++)
o(0x3d400000 |
(sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
j | j << 10); // ldr ([sdq])(*),[x0,#(j * sz)]
}
else
gv(RC_FRET);
break;
default:
assert(0);
}
}
ST_FUNC void gfunc_epilog(void)
{
if (loc) {
// Insert instructions to subtract size of stack frame from SP.
unsigned char *ptr = cur_text_section->data + arm64_func_sub_sp_offset;
uint64_t diff = (-loc + 15) & ~15;
if (!(diff >> 24)) {
if (diff & 0xfff) // sub sp,sp,#(diff & 0xfff)
write32le(ptr, 0xd10003ff | (diff & 0xfff) << 10);
if (diff >> 12) // sub sp,sp,#(diff >> 12),lsl #12
write32le(ptr + 4, 0xd14003ff | (diff >> 12) << 10);
}
else {
// In this case we may subtract more than necessary,
// but always less than 17/16 of what we were aiming for.
int i = 0;
int j = 0;
while (diff >> 20) {
diff = (diff + 0xffff) >> 16;
++i;
}
while (diff >> 16) {
diff = (diff + 1) >> 1;
++j;
}
write32le(ptr, 0xd2800010 | diff << 5 | i << 21);
// mov x16,#(diff),lsl #(16 * i)
write32le(ptr + 4, 0xcb3063ff | j << 10);
// sub sp,sp,x16,lsl #(j)
}
}
o(0x910003bf); // mov sp,x29
o(0xa8ce7bfd); // ldp x29,x30,[sp],#224
o(0xd65f03c0); // ret
}
// Generate forward branch to label:
ST_FUNC int gjmp(int t)
{
int r = ind;
o(t);
return r;
}
// Generate branch to known address:
ST_FUNC void gjmp_addr(int a)
{
assert(a - ind + 0x8000000 < 0x10000000);
o(0x14000000 | ((a - ind) >> 2 & 0x3ffffff));
}
ST_FUNC int gtst(int inv, int t)
{
int bt = vtop->type.t & VT_BTYPE;
if (bt == VT_LDOUBLE) {
uint32_t a, b, f = fltr(gv(RC_FLOAT));
a = get_reg(RC_INT);
vpushi(0);
vtop[0].r = a;
b = get_reg(RC_INT);
a = intr(a);
b = intr(b);
o(0x4e083c00 | a | f << 5); // mov x(a),v(f).d[0]
( run in 1.111 second using v1.01-cache-2.11-cpan-df04353d9ac )