Skip to content

Commit c07fdc5

Browse files
authored
add complex multiply and divide (dlang#22611)
1 parent f681e07 commit c07fdc5

File tree

4 files changed

+99
-15
lines changed

4 files changed

+99
-15
lines changed

compiler/src/dmd/backend/arm/cod1.d

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,10 @@ enum CLIB_A
14791479
lttf2,
14801480
letf2,
14811481
memset,
1482+
mulsc3,
1483+
muldc3,
1484+
divsc3,
1485+
divdc3,
14821486
}
14831487

14841488
private
@@ -1517,12 +1521,21 @@ void initClibInfo(ref Symbol*[CLIB_A.max + 1] clibsyms, ref ClibInfo[CLIB_A.max
15171521
private
15181522
void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t objfmt, exefmt_t exe)
15191523
{
1524+
enum r0r1 = mask(32) | mask(33);
1525+
enum r2r3 = r0r1 >> 2;
1526+
15201527
void declare(string name)
15211528
{
15221529
s = symboly(name, mask(32));
15231530
cinfo.retregs = mask(32);
15241531
}
15251532

1533+
void declare2(string name)
1534+
{
1535+
s = symboly(name, r0r1 | r2r3);
1536+
cinfo.retregs = r0r1;
1537+
}
1538+
15261539
switch (clib)
15271540
{
15281541
case CLIB_A.realToDouble:
@@ -1588,6 +1601,11 @@ void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t obj
15881601
break;
15891602
}
15901603

1604+
case CLIB_A.mulsc3: declare2("__mulsc3"); break;
1605+
case CLIB_A.muldc3: declare2("__muldc3"); break;
1606+
case CLIB_A.divsc3: declare2("__divsc3"); break;
1607+
case CLIB_A.divdc3: declare2("__divdc3"); break;
1608+
15911609
default:
15921610
assert(0);
15931611
}

compiler/src/dmd/backend/arm/cod2.d

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,20 @@ void cdmul(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
300300

301301
if (tyfloating(ty1))
302302
{
303+
if (tycomplex(ty1))
304+
{
305+
regm_t retregs1 = mask(32) | mask(33);
306+
codelem(cg, cdb, e1, retregs1, false);
307+
regm_t retregs2 = mask(34) | mask(35);
308+
scodelem(cg, cdb, e2, retregs2, retregs1, false);
309+
if (ty1 == TYcfloat)
310+
callclib(cdb,e,CLIB_A.mulsc3,pretregs,0);
311+
else if (ty1 == TYcdouble)
312+
callclib(cdb,e,CLIB_A.muldc3,pretregs,0);
313+
else
314+
assert(0);
315+
return;
316+
}
303317
cdorth(cg, cdb, e, pretregs);
304318
return;
305319
}
@@ -356,6 +370,20 @@ void cddiv(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
356370

357371
if (tyfloating(ty1))
358372
{
373+
if (tycomplex(ty1))
374+
{
375+
regm_t retregs1 = mask(32) | mask(33);
376+
codelem(cg, cdb, e1, retregs1, false);
377+
regm_t retregs2 = mask(34) | mask(35);
378+
scodelem(cg, cdb, e2, retregs2, retregs1, false);
379+
if (ty1 == TYcfloat)
380+
callclib(cdb,e,CLIB_A.divsc3,pretregs,0);
381+
else if (ty1 == TYcdouble)
382+
callclib(cdb,e,CLIB_A.divdc3,pretregs,0);
383+
else
384+
assert(0);
385+
return;
386+
}
359387
cdorth(cg, cdb, e, pretregs);
360388
return;
361389
}

compiler/src/dmd/backend/arm/cod4.d

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -478,13 +478,28 @@ void floatOpAss(ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
478478
{
479479
//printf("floatOpass(e=%p, pretregs = %s)\n",e,regm_str(pretregs));
480480
//elem_print(e);
481+
/* pretregs = registers being returned
482+
* idxregs = registers used for EA
483+
* retregs1 = registers for e.E1
484+
* retregs2 = registers for e.E2
485+
* retregs = result registers
486+
* So:
487+
* idxregs = &e1
488+
* retregs1 = *idxregs
489+
* retregs2 = e2
490+
* retregs = retregs1 op retregs2
491+
* *idxregs = retregs
492+
* pretregs = retregs
493+
*/
481494
elem* e1 = e.E1;
482495
tym_t ty1 = tybasic(e1.Ety);
483496
auto sz1 = _tysize[ty1];
484497
code cs;
485498
regm_t retregs;
486499
reg_t reg;
487500
bool isPair = isRegisterPair(true, ty1, 0);
501+
if (isPair)
502+
sz1 /= 2;
488503

489504
if (e.Eoper == OPnegass)
490505
{
@@ -493,7 +508,6 @@ void floatOpAss(ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
493508
if (isPair)
494509
{
495510
reg_t reglsw, regmsw;
496-
sz1 /= 2;
497511
assert(sz1 <= 8); // TODO AArch64 128 bit operands
498512
uint ftype = INSTR.szToFtype(sz1);
499513
if (cs.reg != NOREG)
@@ -575,12 +589,14 @@ void floatOpAss(ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
575589
}
576590

577591
elem* e2 = e.E2;
578-
regm_t rretregs = INSTR.FLOATREGS & ~pretregs;
579-
if (!rretregs)
580-
rretregs = INSTR.FLOATREGS;
592+
regm_t retregs2 = INSTR.FLOATREGS & ~pretregs;
593+
if (!retregs2)
594+
retregs2 = INSTR.FLOATREGS;
595+
if (isPair && (e.Eoper == OPmulass || e.Eoper == OPdivass))
596+
retregs2 = mask(34)|mask(35); // v2|v3
581597

582-
codelem(cgstate,cdb,e2,rretregs,false); // eval right leaf
583-
reg_t rreg = findreg(rretregs);
598+
codelem(cgstate,cdb,e2,retregs2,false); // eval right leaf
599+
reg_t rreg = findreg(retregs2);
584600

585601
bool regvar = false;
586602
if (0 && config.flags4 & CFG4optimized) // TODO AArch64
@@ -603,10 +619,12 @@ void floatOpAss(ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
603619

604620
if (!regvar)
605621
{
606-
getlvalue(cdb,cs,e1,rretregs,RM.rw); // get EA
607-
retregs = pretregs & INSTR.FLOATREGS & ~rretregs;
622+
getlvalue(cdb,cs,e1,retregs2,RM.rw); // get EA
623+
retregs = pretregs & INSTR.FLOATREGS & ~retregs2;
608624
if (!retregs)
609-
retregs = INSTR.FLOATREGS & ~rretregs;
625+
retregs = INSTR.FLOATREGS & ~retregs2;
626+
if (isPair && (e.Eoper == OPmulass || e.Eoper == OPdivass))
627+
retregs = mask(32)|mask(33); // v0|v1
610628
allocreg(cdb,retregs,ty1);
611629
reg = findreg(isPair ? retregs & INSTR.LSW : retregs);
612630
if (isPair)
@@ -618,41 +636,59 @@ void floatOpAss(ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
618636

619637
if (isPair)
620638
{
621-
sz1 /= 2;
622-
rreg = findreg(rretregs & INSTR.LSW);
639+
rreg = findreg(retregs2 & INSTR.LSW);
623640
reg_t Rd = reg, Rn = rreg, Rm = reg; // reg = rreg + reg
624641
const uint ftype = INSTR.szToFtype(sz1);
642+
uint clib;
643+
assert(sz1 != 2 && sz1 != 16); // halffloat and float128
625644
switch (e.Eoper)
626645
{
627646
// FADD/FSUB (extended register)
628647
// http://www.scs.stanford.edu/~zyedidia/arm64/encodingindex.html#floatdp2
629648
case OPaddass:
630649
cdb.gen1(INSTR.fadd_float(ftype,Rn,Rm,Rd)); // FADD Rd,Rn,Rm
650+
L1:
631651
if (!regvar)
632652
{
633653
storeToEA(cs,reg,sz1);
634654
cdb.gen(&cs);
635655
}
636656

637657
reg = findreg(retregs & INSTR.MSW);
638-
rreg = findreg(rretregs & INSTR.MSW);
658+
rreg = findreg(retregs2 & INSTR.MSW);
639659
if (cs.reg == NOREG)
640660
cs.IEV1.Voffset += sz1;
641661
else
642662
cs.reg = reg;
643663
loadFromEA(cs,reg,sz1,sz1);
644664
cdb.gen(&cs);
645665
Rd = reg, Rn = rreg, Rm = reg; // reg = rreg + reg
646-
cdb.gen1(INSTR.fadd_float(ftype,Rn,Rm,Rd)); // FADD Rd,Rn,Rm
666+
if (e.Eoper == OPaddass)
667+
cdb.gen1(INSTR.fadd_float(ftype,Rn,Rm,Rd)); // FADD Rd,Rn,Rm
668+
else
669+
cdb.gen1(INSTR.fsub_float(ftype,Rn,Rm,Rd)); // FSUB Rd,Rn,Rm
647670
break;
648671

649672
case OPminass:
650673
cdb.gen1(INSTR.fsub_float(ftype,Rn,Rm,Rd)); // FSUB Rd,Rn,Rm
651-
break;
674+
goto L1;
652675

653676
case OPmulass:
677+
clib = sz1 == 8 ? CLIB_A.muldc3 : CLIB_A.mulsc3;
678+
goto Lclib;
679+
654680
case OPdivass:
655-
assert(0); // TODO AArch64
681+
clib = sz1 == 8 ? CLIB_A.divdc3 : CLIB_A.divsc3;
682+
Lclib:
683+
regm_t idxregs = idxregm(cs);
684+
callclib(cdb,e,clib,pretregs,idxregs);
685+
if (!regvar)
686+
{
687+
storeToEA(cs,reg,sz1);
688+
cdb.gen(&cs);
689+
cs.IEV1.Voffset += sz1;
690+
}
691+
break;
656692

657693
default:
658694
assert(0);

compiler/src/dmd/backend/x86/cod2.d

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ bool movOnly(const elem* e)
8080
/********************************
8181
* Determine index registers used by addressing mode.
8282
* Index is rm of modregrm field.
83+
* Params:
84+
* c = code with EA filled in
8385
* Returns:
8486
* mask of index registers
8587
*/

0 commit comments

Comments
 (0)