diff --git a/compiler/src/dmd/backend/arm/cod1.d b/compiler/src/dmd/backend/arm/cod1.d index 1643d460da..70a23197c3 100644 --- a/compiler/src/dmd/backend/arm/cod1.d +++ b/compiler/src/dmd/backend/arm/cod1.d @@ -1314,6 +1314,146 @@ void fixresult(ref CodeBuilder cdb, elem* e, regm_t retregs, ref regm_t outretre } } +/******************************* + * Extra information about each CLIB_A runtime library function. + */ + +private +enum CLIB_A +{ + realToDouble, + doubleToReal, +} + +private +struct ClibInfo +{ + regm_t retregs; // registers that 32 bit result is returned in +} + +__gshared int clib_inited = false; // true if initialized + +@trusted private +Symbol* symboly(string name, regm_t desregs) +{ + Symbol* s = symbol_calloc(name); + s.Stype = tsclib; + s.Sclass = SC.extern_; + s.Sfl = FL.func; + s.Ssymnum = 0; + s.Sregsaved = fregsaved; // assume C conventions + return s; +} + +private +void initClibInfo(ref Symbol*[CLIB_A.max + 1] clibsyms, ref ClibInfo[CLIB_A.max + 1] clibinfo) +{ + foreach (s; clibsyms[]) + { + if (s) + { + s.Sxtrnnum = 0; + s.Stypidx = 0; + } + } +} + +private +void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t objfmt, exefmt_t exe) +{ + switch (clib) + { + case CLIB_A.realToDouble: + { + string name = "__trunctfdf2"; + s = symboly(name, mask(32)); + cinfo.retregs = mask(32); + break; + } + + case CLIB_A.doubleToReal: + { + string name = "__extenddftf2"; + s = symboly(name, mask(32)); + cinfo.retregs = mask(32); + break; + } + + default: + assert(0); + } +} + +@trusted private +void getClibInfo(uint clib, Symbol** ps, ClibInfo** pinfo, objfmt_t objfmt, exefmt_t exe) +{ + static Symbol*[CLIB_A.max + 1] clibsyms; + static ClibInfo[CLIB_A.max + 1] clibinfo; + + if (!clib_inited) + { + initClibInfo(clibsyms, clibinfo); + clib_inited = true; + } + + ClibInfo* cinfo = &clibinfo[clib]; + Symbol* s = clibsyms[clib]; + if (!s) + { + getClibFunction(clib, s, cinfo, objfmt, exe); + clibsyms[clib] = s; + } + + *ps = s; + *pinfo = cinfo; +} + +/******************************** + * Generate code sequence to call C runtime library support routine. + * clib = CLIB_A.xxxx + * keepmask = mask of registers not to destroy. Currently can + * handle only 1. Should use a temporary rather than + * push/pop for speed. + */ + +@trusted +void callclib(ref CodeBuilder cdb, elem* e, uint clib, ref regm_t pretregs, regm_t keepmask) +{ + //printf("callclib(e = %p, clib = %d, pretregs = %s, keepmask = %s\n", e, clib, regm_str(pretregs), regm_str(keepmask)); + //elem_print(e); + + Symbol* s; + ClibInfo* cinfo; + getClibInfo(clib, &s, &cinfo, config.objfmt, config.exe); + + getregs(cdb,(~s.Sregsaved & (cgstate.allregs | INSTR.FLOATREGS | mask(cgstate.BP)) & ~keepmask)); // mask of regs destroyed + keepmask &= ~s.Sregsaved; + int npushed = popcnt(keepmask); + CodeBuilder cdbpop; + cdbpop.ctor(); + gensaverestore(keepmask, cdb, cdbpop); + + makeitextern(s); + int nalign = 0; + if (STACKALIGN >= 16) + { // Align the stack (assume no args on stack) + int npush = npushed * REGSIZE + cgstate.stackpush; + if (npush & (STACKALIGN - 1)) + { nalign = STACKALIGN - (npush & (STACKALIGN - 1)); + cod3_stackadj(cdb, nalign); + } + } + + cdb.gencs1(INSTR.branch_imm(1,0),0,FL.func,s); // CALL s + if (nalign) + cod3_stackadj(cdb, -nalign); + cgstate.calledafunc = 1; + + cdb.append(cdbpop); + fixresult(cdb, e, cinfo.retregs, pretregs); +} + + /******************************* * Generate code sequence for function call. */ diff --git a/compiler/src/dmd/backend/arm/cod3.d b/compiler/src/dmd/backend/arm/cod3.d index e60f4dfba3..7b2bbf55a8 100644 --- a/compiler/src/dmd/backend/arm/cod3.d +++ b/compiler/src/dmd/backend/arm/cod3.d @@ -68,7 +68,7 @@ nothrow: @trusted void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint idx) { - // TODO AArch64 floating point registers + assert(reg < 32); // TODO AArch64 floating point registers if (!regsave.alignment) regsave.alignment = REGSIZE; idx = regsave.idx; @@ -96,7 +96,7 @@ void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint @trusted void REGSAVE_restore(const ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, uint idx) { - // TODO AArch64 floating point registers + assert(reg < 32); // TODO AArch64 floating point registers // LDR reg,[BP, #idx] code cs; cs.reg = reg; diff --git a/compiler/src/dmd/backend/x86/cod1.d b/compiler/src/dmd/backend/x86/cod1.d index 657ab62757..51c20d5c18 100644 --- a/compiler/src/dmd/backend/x86/cod1.d +++ b/compiler/src/dmd/backend/x86/cod1.d @@ -37,6 +37,7 @@ import dmd.backend.ty; import dmd.backend.type; import dmd.backend.x86.xmm; import dmd.backend.arm.cod1; +import dmd.backend.arm.instr : INSTR; import dmd.backend.cg : segfl, stackfl; @@ -349,7 +350,7 @@ uint gensaverestore(regm_t regm,ref CodeBuilder cdbsave,ref CodeBuilder cdbresto if (cgstate.AArch64) { - regm &= cgstate.allregs | mask(cgstate.BP); + regm &= cgstate.allregs | mask(cgstate.BP) | INSTR.FLOATREGS; if (!regm) return 0; @@ -2092,6 +2093,7 @@ void fixresult(ref CodeBuilder cdb, elem* e, regm_t retregs, ref regm_t outretre * Extra information about each CLIB runtime library function. */ +private enum { INF32 = 1, /// if 32 bit only @@ -2102,6 +2104,7 @@ enum INFpusheabcdx = 0x20, /// pass EAX/EBX/ECX/EDX on stack, callee does ret 16 } +private struct ClibInfo { regm_t retregs16; /* registers that 16 bit result is returned in */ @@ -2114,6 +2117,7 @@ struct ClibInfo int clib_inited = false; // true if initialized +private Symbol* symboly(string name, regm_t desregs) { Symbol* s = symbol_calloc(name); @@ -2125,6 +2129,7 @@ Symbol* symboly(string name, regm_t desregs) return s; } +private void initClibInfo(ref Symbol*[CLIB.MAX] clibsyms, ref ClibInfo[CLIB.MAX] clibinfo) { for (size_t i = 0; i < CLIB.MAX; ++i) @@ -2139,6 +2144,7 @@ void initClibInfo(ref Symbol*[CLIB.MAX] clibsyms, ref ClibInfo[CLIB.MAX] clibinf } } +private void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t objfmt, exefmt_t exe) { const uint ex_unix = (EX_LINUX | EX_LINUX64 | @@ -2805,6 +2811,7 @@ void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t obj } } +private void getClibInfo(uint clib, Symbol** ps, ClibInfo** pinfo, objfmt_t objfmt, exefmt_t exe) { static Symbol*[CLIB.MAX] clibsyms;