Alien-TinyCC
view release on metacpan or search on metacpan
src/x86_64-gen.c view on Meta::CPAN
if ((vtop->r & VT_VALMASK) == VT_LLOCAL) {
SValue v1;
r = get_reg(RC_INT);
v1.type.t = VT_PTR;
v1.r = VT_LOCAL | VT_LVAL;
v1.c.ul = fc;
load(r, &v1);
fc = 0;
}
assert(!(vtop[-1].r & VT_LVAL));
if (swapped) {
assert(vtop->r & VT_LVAL);
gv(RC_FLOAT);
vswap();
}
if ((ft & VT_BTYPE) == VT_DOUBLE) {
o(0xf2);
} else {
o(0xf3);
}
o(0x0f);
o(0x58 + a);
if (vtop->r & VT_LVAL) {
gen_modrm(vtop[-1].r, r, vtop->sym, fc);
} else {
o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8);
}
vtop--;
}
}
}
/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
and 'long long' cases. */
void gen_cvt_itof(int t)
{
if ((t & VT_BTYPE) == VT_LDOUBLE) {
save_reg(TREG_ST0);
gv(RC_INT);
if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
/* signed long long to float/double/long double (unsigned case
is handled generically) */
o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
o(0x242cdf); /* fildll (%rsp) */
o(0x08c48348); /* add $8, %rsp */
} else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
(VT_INT | VT_UNSIGNED)) {
/* unsigned int to float/double/long double */
o(0x6a); /* push $0 */
g(0x00);
o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
o(0x242cdf); /* fildll (%rsp) */
o(0x10c48348); /* add $16, %rsp */
} else {
/* int to float/double/long double */
o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
o(0x2404db); /* fildl (%rsp) */
o(0x08c48348); /* add $8, %rsp */
}
vtop->r = TREG_ST0;
} else {
int r = get_reg(RC_FLOAT);
gv(RC_INT);
o(0xf2 + ((t & VT_BTYPE) == VT_FLOAT?1:0));
if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
(VT_INT | VT_UNSIGNED) ||
(vtop->type.t & VT_BTYPE) == VT_LLONG) {
o(0x48); /* REX */
}
o(0x2a0f);
o(0xc0 + (vtop->r & VT_VALMASK) + REG_VALUE(r)*8); /* cvtsi2sd */
vtop->r = r;
}
}
/* convert from one floating point type to another */
void gen_cvt_ftof(int t)
{
int ft, bt, tbt;
ft = vtop->type.t;
bt = ft & VT_BTYPE;
tbt = t & VT_BTYPE;
if (bt == VT_FLOAT) {
gv(RC_FLOAT);
if (tbt == VT_DOUBLE) {
o(0x140f); /* unpcklps */
o(0xc0 + REG_VALUE(vtop->r)*9);
o(0x5a0f); /* cvtps2pd */
o(0xc0 + REG_VALUE(vtop->r)*9);
} else if (tbt == VT_LDOUBLE) {
save_reg(RC_ST0);
/* movss %xmm0,-0x10(%rsp) */
o(0x110ff3);
o(0x44 + REG_VALUE(vtop->r)*8);
o(0xf024);
o(0xf02444d9); /* flds -0x10(%rsp) */
vtop->r = TREG_ST0;
}
} else if (bt == VT_DOUBLE) {
gv(RC_FLOAT);
if (tbt == VT_FLOAT) {
o(0x140f66); /* unpcklpd */
o(0xc0 + REG_VALUE(vtop->r)*9);
o(0x5a0f66); /* cvtpd2ps */
o(0xc0 + REG_VALUE(vtop->r)*9);
} else if (tbt == VT_LDOUBLE) {
save_reg(RC_ST0);
/* movsd %xmm0,-0x10(%rsp) */
o(0x110ff2);
o(0x44 + REG_VALUE(vtop->r)*8);
o(0xf024);
o(0xf02444dd); /* fldl -0x10(%rsp) */
vtop->r = TREG_ST0;
}
} else {
( run in 1.185 second using v1.01-cache-2.11-cpan-39bf76dae61 )