@@ -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 );
0 commit comments