diff --git a/arm64-gen.c b/arm64-gen.c index 5bdc29e4..0331532e 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -1849,6 +1849,37 @@ ST_FUNC void gen_opf(int op) { uint32_t x, a, b, dbl; + if (op == TOK_NEG) { + switch (vtop[0].type.t & VT_BTYPE) { + case VT_LDOUBLE: + vpush_helper_func(TOK___negtf2); + vrott(2); + gfunc_call(1); + vpushi(0); + vtop->type.t = VT_LDOUBLE; + vtop->r = REG_FRET; + break; + + case VT_FLOAT: + case VT_DOUBLE: + gv(RC_FLOAT); + dbl = vtop[0].type.t == VT_DOUBLE; + + a = fltr(vtop[0].r); + vtop--; + x = get_reg(RC_FLOAT); + vtop++; + vtop[0].r = x; + x = fltr(x); + + o(0x1e214000 | dbl << 22 | x | a << 5); + break; + default: + assert(0); + } + return; + } + if (vtop[0].type.t == VT_LDOUBLE) { CType type = vtop[0].type; int func = 0; diff --git a/lib/lib-arm64.c b/lib/lib-arm64.c index 226827e9..5eeb8843 100644 --- a/lib/lib-arm64.c +++ b/lib/lib-arm64.c @@ -373,6 +373,17 @@ long double __divtf3(long double fa, long double fb) return f3_round(x_sgn, x_exp, x); } +long double __negtf2(long double f) +{ + u128_t a; + + memcpy(&a, &f, 16); + a.x1 ^= 1UL << 63; + memcpy(&f, &a, 16); + + return f; +} + long double __extendsftf2(float f) { long double fx; diff --git a/tccgen.c b/tccgen.c index 6d42de67..0ea6c288 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2504,7 +2504,7 @@ static void gen_opic(int op) } } -#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386 +#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386 || defined TCC_TARGET_ARM64 # define gen_negf gen_opf #elif defined TCC_TARGET_ARM void gen_negf(int op) diff --git a/tcctok.h b/tcctok.h index 4a16a22f..b7cc9d40 100644 --- a/tcctok.h +++ b/tcctok.h @@ -316,6 +316,7 @@ DEF(TOK___extenddftf2, "__extenddftf2") DEF(TOK___trunctfsf2, "__trunctfsf2") DEF(TOK___trunctfdf2, "__trunctfdf2") + DEF(TOK___negtf2, "__negtf2") DEF(TOK___fixtfsi, "__fixtfsi") DEF(TOK___fixtfdi, "__fixtfdi") DEF(TOK___fixunstfsi, "__fixunstfsi")