@@ -1424,8 +1424,8 @@ private void cdmemsetn(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pr
14241424@trusted
14251425void cdstreq (ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
14261426{
1427- // printf("cdstreq(e = %p, pretregs = %s)\n", e, regm_str(pretregs));
1428- // elem_print(e);
1427+ printf(" cdstreq(e = %p, pretregs = %s)\n " , e, regm_str(pretregs));
1428+ elem_print(e);
14291429 char need_DS = false ;
14301430 elem* e1 = e.E1 ;
14311431 elem* e2 = e.E2 ;
@@ -1467,101 +1467,132 @@ void cdstreq(ref CGstate cg, ref CodeBuilder cdb,elem* e,ref regm_t pretregs)
14671467
14681468 regm_t regm = cg.allregs & ~ (srcregs | dstregs);
14691469 allocreg(cdb, regm, TYint);
1470- reg_t reg = findreg(regm);
1470+ reg_t Rv = findreg(regm);
1471+
1472+ reg_t Rs = findreg(srcregs);
1473+ reg_t Rd = findreg(dstregs);
14711474
14721475 getregs(cdb,srcregs | dstregs | regm);
14731476 if (numbytes <= REGSIZE * 7 )
14741477 {
14751478 code csrc;
1476- csrc.base = findreg(srcregs) ;
1479+ csrc.base = Rs ;
14771480 csrc.index = NOREG ;
14781481 csrc.reg = NOREG ;
14791482
14801483 code cdst;
1481- cdst.base = findreg(dstregs) ;
1484+ cdst.base = Rd ;
14821485 cdst.index = NOREG ;
14831486 cdst.reg = NOREG ;
14841487
14851488 ulong offset;
14861489
14871490 while (numbytes >= REGSIZE )
14881491 {
1489- loadFromEA(csrc,reg ,8 ,8 );
1492+ loadFromEA(csrc,Rv ,8 ,8 );
14901493 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1491- storeToEA(cdst,reg ,8 );
1494+ storeToEA(cdst,Rv ,8 );
14921495 cdb.genc1(cdst.Iop,0 ,FL .offset,offset);
14931496 offset += REGSIZE ;
14941497 numbytes -= REGSIZE ;
14951498 }
14961499
14971500 while (numbytes >= 4 )
14981501 {
1499- loadFromEA(csrc,reg ,4 ,4 );
1502+ loadFromEA(csrc,Rv ,4 ,4 );
15001503 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1501- storeToEA(cdst,reg ,4 );
1504+ storeToEA(cdst,Rv ,4 );
15021505 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
15031506 offset += 4 ;
15041507 numbytes -= 4 ;
15051508 }
15061509
15071510 while (numbytes >= 2 )
15081511 {
1509- loadFromEA(csrc,reg ,4 ,2 );
1512+ loadFromEA(csrc,Rv ,4 ,2 );
15101513 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1511- storeToEA(cdst,reg ,2 );
1514+ storeToEA(cdst,Rv ,2 );
15121515 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
15131516 offset += 2 ;
15141517 numbytes -= 2 ;
15151518 }
15161519
15171520 if (numbytes)
15181521 {
1519- loadFromEA(csrc,reg ,4 ,1 );
1522+ loadFromEA(csrc,Rv ,4 ,1 );
15201523 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1521- storeToEA(cdst,reg ,1 );
1524+ storeToEA(cdst,Rv ,1 );
15221525 cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
15231526 }
15241527 }
15251528 else
15261529 {
1527- if (e1) assert (0 ); // TODO AArch64
1528- static if (1 )
1529- {
1530+ /*
1531+ mov Rc, #count*8
1532+ mov Ri, #0x0
1533+ L2: ldr Rv, [Rs, Ri]
1534+ str Rv, [Rd, Ri]
1535+ add Ri, Ri, #8
1536+ cmp Ri, Rc
1537+ b.ne L2
1538+ */
1539+
15301540 uint remainder = numbytes & (REGSIZE - 1 );
15311541 numbytes /= REGSIZE ; // number of words
1532- getregs_imm(cdb,mCX);
1533- movregconst(cdb,CX ,numbytes,0 ); // # of bytes/words
1534- cdb.gen1(0xF3 ); // REP
1535- if (REGSIZE == 8 )
1536- cdb.gen1(REX | REX_W );
1537- cdb.gen1(0xA5 ); // REP MOVSD
1538- cgstate.regimmed_set(CX ,0 ); // note that CX == 0
1539- if (I64 && remainder >= 4 )
1542+
1543+ regm_t iregs = cg.allregs & ~ (srcregs | dstregs | regm);
1544+ reg_t Ri = allocreg(cdb,iregs,TYnptr);
1545+
1546+ regm_t cregs = cg.allregs & ~ (srcregs | dstregs | regm | iregs);
1547+ reg_t Rc = allocreg(cdb,cregs,TYnptr);
1548+
1549+ code csrc;
1550+ csrc.base = Rs;
1551+ csrc.index = Ri;
1552+ csrc.reg = NOREG ;
1553+
1554+ code cdst;
1555+ csrc.base = Rd;
1556+ csrc.index = Ri;
1557+ csrc.reg = NOREG ;
1558+
1559+ movregconst(cdb,Rc,numbytes * 8 ,0 ); // mov Rc,#count * 8
1560+ movregconst(cdb,Ri,0 ,0 ); // mov Ri,0
1561+
1562+ loadFromEA(csrc,Rv,8 ,8 ); // L2: ldr Rv,[Rs,Ri]
1563+ cdb.genc1(csrc.Iop,0 ,FL .offset,0 );
1564+ code* L2 = cdb.last();
1565+ storeToEA(cdst,Rv,8 ); // str Rv,[Rd,Ri]
1566+ cdb.genc1(cdst.Iop,0 ,FL .offset,0 );
1567+
1568+ cdb.gen1(INSTR .add_addsub_imm(1 ,0 ,8 ,Ri,Ri)); // add Ri,Ri,#0x8 https://www.scs.stanford.edu/~zyedidia/arm64/add_addsub_imm.html
1569+ cdb.gen1(INSTR .cmp_shift(0 ,Rc,0 ,0 ,Ri)); // cmp Ri,Rc
1570+ genBranch(cdb,COND .ne,FL .code,cast (block* )L2 ); // b.ne L2
1571+
1572+ uint offset = 0 ;
1573+ if (remainder & 4 )
15401574 {
1541- cdb.gen1(0xA5 ); // MOVSD
1542- remainder -= 4 ;
1575+ loadFromEA(csrc,Rv,4 ,4 ); // ldr Rv,[Rs,Ri]
1576+ cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1577+ storeToEA(cdst,Rv,4 ); // str Rv,[Rd,Ri]
1578+ cdb.genc1(cdst.Iop,0 ,FL .offset,offset);
1579+ offset += 4 ;
15431580 }
1544- for (; remainder; remainder -- )
1581+ if ( remainder & 2 )
15451582 {
1546- cdb.gen1(0xA4 ); // MOVSB
1583+ loadFromEA(csrc,Rv,2 ,2 ); // ldr Rv,[Rs,Ri]
1584+ cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1585+ storeToEA(cdst,Rv,2 ); // str Rv,[Rd,Ri]
1586+ cdb.genc1(cdst.Iop,0 ,FL .offset,offset);
1587+ offset += 2 ;
15471588 }
1548- }
1549- else
1550- {
1551- uint movs;
1552- if (numbytes & (REGSIZE - 1 )) // if odd
1553- movs = 0xA4 ; // MOVSB
1554- else
1589+ if (remainder & 1 )
15551590 {
1556- movs = 0xA5 ; // MOVSW
1557- numbytes /= REGSIZE ; // # of words
1591+ loadFromEA(csrc,Rv,1 ,1 ); // ldr Rv,[Rs,Ri]
1592+ cdb.genc1(csrc.Iop,0 ,FL .offset,offset);
1593+ storeToEA(cdst,Rv,1 ); // str Rv,[Rd,Ri]
1594+ cdb.genc1(cdst.Iop,0 ,FL .offset,offset);
15581595 }
1559- getregs_imm(cdb,mCX);
1560- movregconst(cdb,CX ,numbytes,0 ); // # of bytes/words
1561- cdb.gen1(0xF3 ); // REP
1562- cdb.gen1(movs);
1563- cgstate.regimmed_set(CX ,0 ); // note that CX == 0
1564- }
15651596 }
15661597 assert (! (pretregs & mPSW));
15671598 if (pretregs)
@@ -1570,7 +1601,7 @@ else
15701601 // cdb.genc2(0x81,(rex << 16) | modregrm(3,5,DI), type_size(e.ET)); // SUB DI,numbytes
15711602
15721603 const tym = tybasic(e.Ety);
1573- if (tym == TYucent && I64 )
1604+ if (tym == TYucent)
15741605 {
15751606 /* https://issues.dlang.org/show_bug.cgi?id=22175
15761607 * The trouble happens when the struct size does not fit exactly into
@@ -1579,30 +1610,30 @@ else
15791610 */
15801611
15811612 // dereference DI
1582- code cs ;
1583- cs.Iop = 0x8B ;
1584- regm_t retregs = pretregs ;
1613+ regm_t retregs = pretregs & ~ srcregs ;
1614+ if ( ! retregs)
1615+ retregs = cgstate.allregs & ~ srcregs ;
15851616 allocreg(cdb,retregs,tym);
15861617
15871618 reg_t msreg = findreg(retregs & INSTR .MSW );
1588- buildEA(&cs,DI ,- 1 ,1 ,REGSIZE );
1589- code_newreg(&cs,msreg);
1590- cs.Irex |= REX_W ;
1591- cdb.gen(&cs); // MOV msreg,REGSIZE[DI] // msreg is never DI
1619+
1620+ code cs;
1621+ cs.base = Rs;
1622+ cs.index = NOREG ;
1623+ cs.reg = NOREG ;
1624+
1625+ loadFromEA(cs,msreg,8 ,8 ); // ldr msreg,[Rs,REGSIZE]
1626+ cdb.genc1(cs.Iop,0 ,FL .offset,REGSIZE );
15921627
15931628 reg_t lsreg = findreg(retregs & INSTR .LSW );
1594- buildEA(&cs,DI ,- 1 ,1 ,0 );
1595- code_newreg(&cs,lsreg);
1596- cs.Irex |= REX_W ;
1597- cdb.gen(&cs); // MOV lsreg,[DI];
1629+ loadFromEA(cs,lsreg,8 ,8 ); // ldr lsreg,[Rs]
1630+ cdb.genc1(cs.Iop,0 ,FL .offset,0 );
1631+
15981632 fixresult(cdb,e,retregs,pretregs);
15991633 return ;
16001634 }
16011635
1602- regm_t retregs = mDI;
1603- if (pretregs & INSTR .MSW && ! (config.exe & EX_flat))
1604- retregs |= mES;
1605- fixresult(cdb,e,retregs,pretregs);
1636+ fixresult(cdb,e,dstregs,pretregs);
16061637 }
16071638}
16081639
0 commit comments