diff --git a/compiler/src/dmd/backend/arm/cod1.d b/compiler/src/dmd/backend/arm/cod1.d index ff601f6cf78..0ddb69a3bc6 100644 --- a/compiler/src/dmd/backend/arm/cod1.d +++ b/compiler/src/dmd/backend/arm/cod1.d @@ -2274,7 +2274,7 @@ static if (1) int sz = _tysize[tym]; cs.Iflags = 0; flags = outretregs & mPSW; /* save original */ - forregs = outretregs & cgstate.allregs; // XMMREGS ? + forregs = outretregs & (cgstate.allregs | INSTR.FLOATREGS); // XMMREGS ? //if (outretregs & mSTACK) //forregs |= DOUBLEREGS; if (e.Eoper == OPconst) diff --git a/compiler/src/dmd/backend/arm/cod2.d b/compiler/src/dmd/backend/arm/cod2.d index 69b412ce72d..9786bb95550 100644 --- a/compiler/src/dmd/backend/arm/cod2.d +++ b/compiler/src/dmd/backend/arm/cod2.d @@ -59,6 +59,7 @@ import dmd.backend.divcoeff : choose_multiplier, udiv_coefficients; void cdorth(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs) { //printf("cdorth(e = %p, pretregs = %s)\n",e,regm_str(pretregs)); + //elem_print(e); elem* e1 = e.E1; elem* e2 = e.E2; @@ -82,7 +83,15 @@ void cdorth(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs) reg_t Rn = findreg(retregs1); regm_t retregs2 = posregs & ~retregs1; +//printf("retregs1: %s retregs2: %s\n", regm_str(retregs1), regm_str(retregs2)); +static if (0) +{ scodelem(cg, cdb, e2, retregs2, retregs1, false); +} +else +{ + retregs2 = mask(33); +} reg_t Rm = findreg(retregs2); regm_t retregs = pretregs & posregs; @@ -94,21 +103,18 @@ void cdorth(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs) if (tyfloating(ty1)) { + uint ftype = sz == 2 ? 3 : + sz == 4 ? 0 : 1; switch (e.Eoper) { // FADD/FSUB (extended register) // http://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#addsub_ext case OPadd: + cdb.gen1(INSTR.fadd_float(ftype,Rm,Rn,Rd)); // FADD Rd,Rn,Rm + break; + case OPmin: - uint sf = sz == 8; - uint op = e.Eoper == OPadd ? 0 : 1; - uint S = PSW != 0; - uint opt = 0; - uint option = tyToExtend(ty); - uint imm3 = 0; - cdb.gen1(INSTR.addsub_ext(sf, op, S, opt, Rm, option, imm3, Rn, Rd)); - PSW = 0; - pretregs &= ~mPSW; + cdb.gen1(INSTR.fsub_float(ftype,Rm,Rn,Rd)); // FSUB Rd,Rn,Rm break; default: diff --git a/compiler/src/dmd/backend/arm/instr.d b/compiler/src/dmd/backend/arm/instr.d index dfefed011ac..e8f5cfc79e4 100644 --- a/compiler/src/dmd/backend/arm/instr.d +++ b/compiler/src/dmd/backend/arm/instr.d @@ -737,8 +737,56 @@ struct INSTR /* Floating-point compare * Floating-point immediate * Floating-point condistional compare - * Floating-point data-processing (2 source) - * Floating-point conditional select + */ + + /* Floating-point data-processing (2 source) https://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#floatdp2 + */ + static uint floatdp2(uint M, uint S, uint ftype, reg_t Vm, uint opcode, reg_t Vn, reg_t Vd) + { + assert(Vm >= 32 && Vn >= 32 && Vd >= 32); + reg_t Rm = Vm & 31; + reg_t Rn = Vn & 31; + reg_t Rd = Vd & 31; + return (M << 31) | (S << 29) | (0x1E << 24) | (ftype << 22) | (1 << 21) | (Rm << 16) | (opcode << 12) | (2 << 10) | (Rn << 5) | Rd; + } + + /* FMUL (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fmul_float.html + */ + static uint fmul_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,0,Vn,Vd); } + + /* FDIV (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fdiv_float.html + */ + static uint fdiv_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,1,Vn,Vd); } + + /* FADD (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fadd_float.html + */ + static uint fadd_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,2,Vn,Vd); } + + /* FSUB (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fsub_float.html + */ + static uint fsub_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,3,Vn,Vd); } + + /* FMAX (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fmax_float.html + */ + static uint fmax_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,4,Vn,Vd); } + + /* FMIN (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fmin_float.html + */ + static uint fmin_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,5,Vn,Vd); } + + /* FMAXNM (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fmaxnm_float.html + */ + static uint fmaxnm_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,6,Vn,Vd); } + + /* FMINNM (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fminnm_float.html + */ + static uint fminnm_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,7,Vn,Vd); } + + /* FNMUL (scalar) https://www.scs.stanford.edu/~zyedidia/arm64/fnmul_float.html + */ + static uint fnmul_float(uint ftype, reg_t Vm, reg_t Vn, reg_t Vd) { return floatdp2(0,0,ftype,Vm,8,Vn,Vd); } + + /* Floating-point conditional select * Floating-point data-processing (3 source) */ diff --git a/compiler/src/dmd/backend/debugprint.d b/compiler/src/dmd/backend/debugprint.d index 4cbdd9d3c55..4fb1d3a3650 100644 --- a/compiler/src/dmd/backend/debugprint.d +++ b/compiler/src/dmd/backend/debugprint.d @@ -153,7 +153,10 @@ const(char)* tym_str(tym_t ty) const tyb = tybasic(ty); if (tyb >= TYMAX) { - printf("TY %x\n",cast(int)ty); + if (tyb == TYMAX) + printf("TY TYMAX\n"); + else + printf("TY %x\n",cast(int)ty); assert(0); } strcat(p, "TY"); diff --git a/compiler/src/dmd/backend/x86/cgcod.d b/compiler/src/dmd/backend/x86/cgcod.d index ffcfdae8728..f0ed2dfea6b 100644 --- a/compiler/src/dmd/backend/x86/cgcod.d +++ b/compiler/src/dmd/backend/x86/cgcod.d @@ -40,6 +40,7 @@ import dmd.backend.ty; import dmd.backend.type; import dmd.backend.arm.disasmarm; +import dmd.backend.arm.instr; import dmd.backend.x86.code_x86; import dmd.backend.x86.disasm86; @@ -1620,7 +1621,7 @@ static if (0) } tym = tybasic(tym); uint size = _tysize[tym]; - outretregs &= mES | cgstate.allregs | XMMREGS; + outretregs &= mES | cgstate.allregs | XMMREGS | INSTR.FLOATREGS; regm_t retregs = outretregs; regm_t[] lastRetregs = cgstate.lastRetregs[]; @@ -1630,7 +1631,7 @@ static if (0) if ((retregs & cgstate.regcon.mvar) == retregs) // if exactly in reg vars { reg_t outreg; - if (size <= REGSIZE || (retregs & XMMREGS)) + if (size <= REGSIZE || (retregs & XMMREGS) || (retregs & INSTR.FLOATREGS)) { outreg = findreg(retregs); assert(retregs == mask(outreg)); /* no more bits are set */ @@ -3002,7 +3003,7 @@ const(char)* regm_str(regm_t rm) { char[4] buf = void; char c = j < 32 ? 'r' : 'f'; - sprintf(buf.ptr, "c%u", c, j); + sprintf(buf.ptr, "%c%u", c, j); strcat(p, buf.ptr); } } diff --git a/compiler/src/dmd/backend/x86/cod3.d b/compiler/src/dmd/backend/x86/cod3.d index 39468ed8a6b..11e854a1173 100644 --- a/compiler/src/dmd/backend/x86/cod3.d +++ b/compiler/src/dmd/backend/x86/cod3.d @@ -1142,7 +1142,8 @@ static if (NTEXCEPTIONS) case BC.retexp: reg_t reg1, reg2; retregs = allocretregs(cgstate, e.Ety, e.ET, funcsym_p.ty(), reg1, reg2); - //printf("allocretregs returns %s\n", regm_str(mask(reg1) | mask(reg2))); + //printf("reg1: %d, reg2: %d\n", reg1, reg2); + //printf("allocretregs returns %llx %s\n", retregs, regm_str(retregs)); reg_t lreg = NOREG; reg_t mreg = NOREG; @@ -1377,7 +1378,7 @@ static if (NTEXCEPTIONS) @trusted regm_t allocretregs(ref CGstate cgstate, const tym_t ty, type* t, const tym_t tyf, out reg_t reg1, out reg_t reg2) { - //printf("allocretregs() ty: %s\n", tym_str(ty)); + printf("allocretregs() ty: %s\n", tym_str(ty)); reg1 = reg2 = NOREG; auto AArch64 = cgstate.AArch64; @@ -1504,6 +1505,7 @@ regm_t allocretregs(ref CGstate cgstate, const tym_t ty, type* t, const tym_t ty { if (tym == TYMAX) return NOREG; +printf("tym: %s\n", tym_str(tym)); switch (tysize(tym)) { case 1: @@ -1525,6 +1527,8 @@ regm_t allocretregs(ref CGstate cgstate, const tym_t ty, type* t, const tym_t ty assert(tyfb == TYjfunc && I32); return ST01; } + else if (AArch64 && tyfloating(tym)) + return rralloc.fpt(); else if (tysimd(tym)) { return rralloc.xmm(); @@ -1559,6 +1563,8 @@ regm_t allocretregs(ref CGstate cgstate, const tym_t ty, type* t, const tym_t ty reg1 = allocreg(ty1); reg2 = allocreg(ty2); + //printf("reg1: %d reg2: %d NOREG: %d\n", reg1, reg2, NOREG); + //printf("reg1: %llx reg2: %llx ~NOREG: %llx\n", mask(reg1), mask(reg2), ~mask(NOREG)); return (mask(reg1) | mask(reg2)) & ~mask(NOREG); }