diff --git a/compiler/src/dmd/backend/backconfig.d b/compiler/src/dmd/backend/backconfig.d index 0997ba4efc..1cdff29ede 100644 --- a/compiler/src/dmd/backend/backconfig.d +++ b/compiler/src/dmd/backend/backconfig.d @@ -313,6 +313,7 @@ static if (0) configv.vasm = vasm; configv.verbose = verbose; + go.AArch64 = arm; if (optimize) go_flag(go, cast(char*)"-o".ptr); diff --git a/compiler/src/dmd/backend/elem.d b/compiler/src/dmd/backend/elem.d index 34eaa1570c..827d0fa103 100644 --- a/compiler/src/dmd/backend/elem.d +++ b/compiler/src/dmd/backend/elem.d @@ -1144,7 +1144,7 @@ int el_countCommas(const(elem)* e) * Convert floating point constant to a read-only symbol. * Needed iff floating point code can't load immediate constants. */ -@trusted +private @trusted elem* el_convfloat(ref GlobalOptimizer go, elem* e) { //printf("el_convfloat()\n"); elem_print(e); @@ -1232,12 +1232,75 @@ elem* el_convfloat(ref GlobalOptimizer go, elem* e) return e; } +/************************************ + * Convert AArch64 128 bit floating point constant to a read-only symbol. + * Params: + * go = optimizer state + * e = floating point constant + * Returns: + * read-only constant variable + */ +private @trusted +elem* el_convreal(ref GlobalOptimizer go, elem* e) +{ + //printf("el_convfloat()\n"); elem_print(e); + ubyte[32] buffer = void; + + tym_t ty = e.Ety; + int sz = tysize(ty); + assert(sz <= buffer.length); + void* p; + switch (tybasic(ty)) + { + case TYldouble: + case TYildouble: + /* The size, alignment, and padding of long doubles may be different + * from host to target + */ + p = buffer.ptr; + // TODO AArch64 these are supposed to be 128 bit floats, not 80 bit + memset(buffer.ptr, 0, sz); // ensure padding is 0 + memcpy(buffer.ptr, &e.Vldouble, 10); + break; + + case TYcldouble: + p = buffer.ptr; + memset(buffer.ptr, 0, sz); + memcpy(buffer.ptr, &e.Vcldouble.re, 10); + memcpy(buffer.ptr + tysize(TYldouble), &e.Vcldouble.im, 10); + break; + + default: + return e; // not necessary + } + + static if (0) + { + printf("%gL+%gLi\n", cast(double)e.Vcldouble.re, cast(double)e.Vcldouble.im); + printf("el_convfloat() %g %g sz=%d\n", e.Vcdouble.re, e.Vcdouble.im, sz); + printf("el_convfloat(): sz = %d\n", sz); + ushort* p = cast(ushort*)&e.Vcldouble; + for (int i = 0; i < sz/2; i++) printf("%04x ", p[i]); + printf("\n"); + } + + Symbol* s = out_readonly_sym(ty, p, sz); + el_free(e); + + elem* ep = el_ptr(s); + elem* ec = el_una(OPind, ty, ep); + + go.changes++; + //printf("s: %s %d:x%x\n", s.Sident, s.Sseg, s.Soffset); + return ec; +} + /************************************ * Convert vector constant to a read-only symbol. * Needed iff vector code can't load immediate constants. */ -@trusted +private @trusted elem* el_convxmm(ref GlobalOptimizer go, elem* e) { // Do not convert if the constants can be loaded with the special XMM instructions @@ -1272,7 +1335,7 @@ elem* el_convxmm(ref GlobalOptimizer go, elem* e) * stored in the static data segment. */ -@trusted +private @trusted elem* el_convstring(elem* e) { //printf("el_convstring()\n"); @@ -1386,6 +1449,7 @@ void shrinkLongDoubleConstantIfPossible(elem* e) /************************* * Run through a tree converting it to CODGEN. */ +public @trusted elem* el_convert(ref GlobalOptimizer go, elem* e) { @@ -1400,8 +1464,13 @@ elem* el_convert(ref GlobalOptimizer go, elem* e) case OPconst: if (tyvector(e.Ety)) e = el_convxmm(go, e); - else if (tyfloating(e.Ety) && config.inline8087) - e = el_convfloat(go, e); + else if (tyfloating(e.Ety)) + { + if (config.inline8087) + e = el_convfloat(go, e); + else if (go.AArch64) + e = el_convreal(go, e); + } break; case OPstring: diff --git a/compiler/src/dmd/backend/goh.d b/compiler/src/dmd/backend/goh.d index 7d533fac70..f88c8b46f1 100644 --- a/compiler/src/dmd/backend/goh.d +++ b/compiler/src/dmd/backend/goh.d @@ -74,6 +74,7 @@ struct DefNode */ struct GlobalOptimizer { + bool AArch64; // AArch64 is the target mftype mfoptim; uint changes; // # of optimizations performed