diff --git a/compiler/src/dmd/backend/arm/cod3.d b/compiler/src/dmd/backend/arm/cod3.d index fde9bb6843..15d682901a 100644 --- a/compiler/src/dmd/backend/arm/cod3.d +++ b/compiler/src/dmd/backend/arm/cod3.d @@ -1600,6 +1600,7 @@ void assignaddrc(code* c) case FL.code: case FL.unde: case FL.block: + case FL.switch_: break; default: diff --git a/compiler/src/dmd/backend/arm/cod4.d b/compiler/src/dmd/backend/arm/cod4.d index c2e743f2da..e0f73ddb72 100644 --- a/compiler/src/dmd/backend/arm/cod4.d +++ b/compiler/src/dmd/backend/arm/cod4.d @@ -1406,7 +1406,7 @@ void cdcnvt(ref CGstate cg, ref CodeBuilder cdb,elem* e, ref regm_t pretregs) case OPu64_d: // ucvtf d31,x0 regm_t retregs1 = ALLREGS; codelem(cgstate,cdb,e.E1,retregs1,false); - reg_t Rn = findreg(retregs1); // source integer register + reg_t Rn = findreg(retregs1); // source integer register regm_t retregs = INSTR.FLOATREGS; const tym = tybasic(e.Ety); diff --git a/compiler/src/dmd/backend/arm/disasmarm.d b/compiler/src/dmd/backend/arm/disasmarm.d index 1730a3d2d0..12f5bdb91b 100644 --- a/compiler/src/dmd/backend/arm/disasmarm.d +++ b/compiler/src/dmd/backend/arm/disasmarm.d @@ -2252,16 +2252,20 @@ void disassemble(uint c) @trusted case ldr(1,0,3): p1 = "ldrsh"; goto Lldr; case ldr(2,0,0): p1 = "str"; goto Lldr; case ldr(2,0,1): p1 = "ldr"; goto Lldr; - case ldr(2,0,2): p1 = "ldrsw"; goto Lldr64; + case ldr(2,0,2): p1 = "ldrsw"; goto Lldrsw; case ldr(3,0,0): p1 = "str"; goto Lldr64; case ldr(3,0,1): p1 = "ldr"; goto Lldr64; //case ldr(3,0,2): p1 = "prfm"; + Lldrsw: + p2 = regString(true, Rt); + p3 = eaString(0, cast(ubyte)Rn, imm12 * 4); + break; + Lldr64: is64 = true; Lldr: p2 = regString(is64, Rt); - uint offset = imm12 * (is64 ? 8 : 4); - p3 = eaString(0, cast(ubyte)Rn, offset); + p3 = eaString(0, cast(ubyte)Rn, imm12 * (is64 ? 8 : 4)); break; case ldr(0,1,0): p1 = "str"; goto LsimdFp; diff --git a/compiler/src/dmd/backend/x86/cod3.d b/compiler/src/dmd/backend/x86/cod3.d index 549b5ff88e..42ed8f1f39 100644 --- a/compiler/src/dmd/backend/x86/cod3.d +++ b/compiler/src/dmd/backend/x86/cod3.d @@ -937,7 +937,7 @@ void outblkexitcode(ref CodeBuilder cdb, block* bl, ref int anyspill, const(FL)* case BC.switch_: { assert(!(bl.Bflags & BFL.epilog)); - doswitch(cdb,bl); // hide messy details + doswitch(cgstate,cdb,bl); // hide messy details break; } case BC.jcatch: // D catch clause of try-catch @@ -1598,9 +1598,20 @@ struct CaseVal * Generate comparison of [reg2,reg] with val */ @trusted -private void cmpval(ref CodeBuilder cdb, targ_llong val, uint sz, reg_t reg, reg_t reg2, reg_t sreg) +private void cmpval(CGstate cg, ref CodeBuilder cdb, targ_llong val, uint sz, reg_t reg, reg_t reg2, reg_t sreg) { - if (I64 && sz == 8) + if (cg.AArch64) + { + // TODO AArch64 use CMP https://www.scs.stanford.edu/~zyedidia/arm64/cmp_subs_addsub_imm.html + assert(sreg == NOREG); + regm_t retregs = cg.allregs & ~mask(reg); + sreg = allocreg(cdb,retregs,TYint); + movregconst(cdb,sreg,val,sz == 8 ? 64 : 0); + getregsNoSave(retregs); + assert(reg2 == NOREG); + cdb.gen1(INSTR.cmp_shift(sz == 8, reg, 0, 0, sreg)); // CMP sreg,reg + } + else if (I64 && sz == 8) { assert(reg2 == NOREG); if (val == cast(int)val) // if val is a 64 bit value sign-extended from 32 bits @@ -1630,7 +1641,7 @@ private void cmpval(ref CodeBuilder cdb, targ_llong val, uint sz, reg_t reg, reg } @trusted extern (D) -private void ifthen(ref CodeBuilder cdb, scope CaseVal[] casevals, +private void ifthen(CGstate cg, ref CodeBuilder cdb, scope CaseVal[] casevals, uint sz, reg_t reg, reg_t reg2, reg_t sreg, block* bdefault, bool last) { const ncases = casevals.length; @@ -1640,18 +1651,27 @@ private void ifthen(ref CodeBuilder cdb, scope CaseVal[] casevals, // Compares for casevals[0..pivot] CodeBuilder cdb1; cdb1.ctor(); - ifthen(cdb1, casevals[0 .. pivot], sz, reg, reg2, sreg, bdefault, true); + ifthen(cg, cdb1, casevals[0 .. pivot], sz, reg, reg2, sreg, bdefault, true); // Compares for casevals[pivot+1..ncases] CodeBuilder cdb2; cdb2.ctor(); - ifthen(cdb2, casevals[pivot + 1 .. $], sz, reg, reg2, sreg, bdefault, last); + ifthen(cg, cdb2, casevals[pivot + 1 .. $], sz, reg, reg2, sreg, bdefault, last); code* c2 = gennop(null); // Compare for caseval[pivot] - cmpval(cdb, casevals[pivot].val, sz, reg, reg2, sreg); - genjmp(cdb,JE,FL.block,casevals[pivot].target); // JE target - // Note uint jump here, as cases were sorted using uint comparisons - genjmp(cdb,JA,FL.code,cast(block*) c2); // JG c2 + cmpval(cg, cdb, casevals[pivot].val, sz, reg, reg2, sreg); + if (cg.AArch64) + { + genBranch(cdb,COND.eq,FL.block,casevals[pivot].target); // equal + // Note uint jump here, as cases were sorted using uint comparisons + genBranch(cdb,COND.cs,FL.code,cast(block*) c2); // greater than + } + else + { + genjmp(cdb,JE,FL.block,casevals[pivot].target); // JE target + // Note uint jump here, as cases were sorted using uint comparisons + genjmp(cdb,JA,FL.code,cast(block*) c2); // JG c2 + } cdb.append(cdb1); cdb.append(c2); @@ -1662,20 +1682,29 @@ private void ifthen(ref CodeBuilder cdb, scope CaseVal[] casevals, foreach (size_t n; 0 .. ncases) { targ_llong val = casevals[n].val; - cmpval(cdb, val, sz, reg, reg2, sreg); + cmpval(cg, cdb, val, sz, reg, reg2, sreg); code* cnext = null; if (reg2 != NOREG) { + assert(!cg.AArch64); cnext = gennop(null); genjmp(cdb,JNE,FL.code,cast(block*) cnext); // JNE cnext cdb.genc2(0x81,modregrm(3,7,reg2),cast(targ_size_t)MSREG(val)); // CMP reg2,MSREG(casevalue) } - genjmp(cdb,JE,FL.block,casevals[n].target); // JE caseaddr + if (cg.AArch64) + genBranch(cdb,COND.eq,FL.block,casevals[n].target); // JE caseaddr + else + genjmp(cdb,JE,FL.block,casevals[n].target); // JE caseaddr cdb.append(cnext); } if (last) // if default is not next block - genjmp(cdb,JMP,FL.block,bdefault); + { + if (cg.AArch64) + genBranch(cdb,COND.al,FL.block,bdefault); + else + genjmp(cdb,JMP,FL.block,bdefault); + } } } @@ -1688,7 +1717,7 @@ private void ifthen(ref CodeBuilder cdb, scope CaseVal[] casevals, */ @trusted -void doswitch(ref CodeBuilder cdb, block* b) +void doswitch(ref CGstate cg, ref CodeBuilder cdb, block* b) { // If switch tables are in code segment and we need a CS: override to get at them bool csseg = cast(bool)(config.flags & CFGromable); @@ -1732,7 +1761,7 @@ void doswitch(ref CodeBuilder cdb, block* b) /* Three kinds of switch strategies - pick one */ const ncases = b.Bswitch.length; - if (ncases <= 3) + if (ncases <= 3 || cg.AArch64) goto Lifthen; else if (I16 && cast(targ_ullong)(vmax - vmin) <= ncases * 2) goto Ljmptab; // >=50% of the table is case values, rest is default @@ -1748,7 +1777,8 @@ void doswitch(ref CodeBuilder cdb, block* b) /*************************************************************************/ { // generate if-then sequence Lifthen: - regm_t retregs = ALLREGS; + //printf("ifthen:\n"); + regm_t retregs = cg.allregs; b.bc = BC.ifthen; scodelem(cgstate,cdb,e,retregs,0,true); reg_t reg, reg2; @@ -1786,8 +1816,8 @@ void doswitch(ref CodeBuilder cdb, block* b) casevals[n].target = list_block(bl); // See if we need a scratch register - if (sreg == NOREG && I64 && sz == 8 && val != cast(int)val) - { regm_t regm = ALLREGS & ~mask(reg); + if (!cg.AArch64 && sreg == NOREG && I64 && sz == 8 && val != cast(int)val) + { regm_t regm = cg.allregs & ~mask(reg); sreg = allocreg(cdb,regm, TYint); } } @@ -1799,7 +1829,7 @@ void doswitch(ref CodeBuilder cdb, block* b) //printf("casevals[%lld] = x%x\n", n, casevals[n].val); // Generate binary tree of comparisons - ifthen(cdb, casevals, sz, reg, reg2, sreg, bdefault, bdefault != b.Bnext); + ifthen(cg, cdb, casevals, sz, reg, reg2, sreg, bdefault, bdefault != b.Bnext); cgstate.stackclean--; return; @@ -1809,7 +1839,7 @@ void doswitch(ref CodeBuilder cdb, block* b) { // Use switch value to index into jump table Ljmptab: - //printf("Ljmptab:\n"); + //printf("jmptab:\n"); b.bc = BC.jmptab; @@ -2013,6 +2043,7 @@ else * Note that it has not been tested with MACHOBJ (OSX). */ Lswitch: + //printf("repne scasw:\n"); regm_t retregs = mAX; // SCASW requires AX if (dword) retregs |= mDX;