@@ -12256,8 +12256,121 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz)
1225612256 }
1225712257}
1225812258
12259+ /*****************************************************************************
12260+ *
12261+ * Handles printing of LARGEJMP pseudo-instruction.
12262+ */
12263+
12264+ void emitter::emitDispLargeJmp(
12265+ instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
12266+ {
12267+ // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
12268+ // difficult-to-find bug.
12269+
12270+ instrDescJmp idJmp;
12271+ instrDescJmp* pidJmp = &idJmp;
12272+
12273+ memset(&idJmp, 0, sizeof(idJmp));
12274+
12275+ const instruction ins = id->idIns();
12276+ instruction reverseIns;
12277+ insFormat reverseFmt;
12278+
12279+ // Reverse the conditional instruction.
12280+ switch (ins)
12281+ {
12282+ case INS_cbz:
12283+ reverseIns = INS_cbnz;
12284+ reverseFmt = IF_BI_1A;
12285+ break;
12286+ case INS_cbnz:
12287+ reverseIns = INS_cbz;
12288+ reverseFmt = IF_BI_1A;
12289+ break;
12290+ case INS_tbz:
12291+ reverseIns = INS_tbnz;
12292+ reverseFmt = IF_BI_1B;
12293+ break;
12294+ case INS_tbnz:
12295+ reverseIns = INS_tbz;
12296+ reverseFmt = IF_BI_1B;
12297+ break;
12298+ default:
12299+ reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
12300+ reverseFmt = IF_BI_0B;
12301+ }
12302+
12303+ pidJmp->idIns(reverseIns);
12304+ pidJmp->idInsFmt(reverseFmt);
12305+ pidJmp->idOpSize(id->idOpSize());
12306+ pidJmp->idAddr()->iiaSetInstrCount(1);
12307+ pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // Share the idDebugOnlyInfo() field.
12308+
12309+ const size_t bcondSizeOrZero = (pCode == NULL) ? 0 : 4; // Branch is 4 bytes.
12310+ emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, pCode, bcondSizeOrZero,
12311+ NULL /* force display of pc-relative branch */);
12312+
12313+ pCode += bcondSizeOrZero;
12314+ offset += 4;
12315+
12316+ // Next, display the unconditional branch.
12317+
12318+ // Reset the local instrDesc.
12319+ memset(&idJmp, 0, sizeof(idJmp));
12320+
12321+ pidJmp->idIns(INS_b);
12322+ pidJmp->idInsFmt(IF_LARGEJMP);
12323+
12324+ if (id->idIsBound())
12325+ {
12326+ pidJmp->idSetIsBound();
12327+ pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
12328+ }
12329+ else
12330+ {
12331+ pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
12332+ }
12333+
12334+ pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // Share the idDebugOnlyInfo() field.
12335+
12336+ const size_t brSizeOrZero = (pCode == NULL) ? 0 : 4; // Unconditional branch is 4 bytes.
12337+ emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, pCode, brSizeOrZero, ig);
12338+ }
12339+
12340+ /*****************************************************************************
12341+ *
12342+ * Wrapper for emitter::emitDispInsHelp() that handles special large jump
12343+ * pseudo-instruction.
12344+ */
12345+
12346+ void emitter::emitDispIns(
12347+ instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
12348+ {
12349+ // Special case: IF_LARGEJMP
12350+
12351+ if ((id->idInsFmt() == IF_LARGEJMP) && id->idIsBound())
12352+ {
12353+ // This is a pseudo-instruction format representing a large conditional branch. See the comment
12354+ // in emitter::emitOutputLJ() for the full description.
12355+ //
12356+ // For this pseudo-instruction, we will actually generate:
12357+ //
12358+ // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
12359+ // b L_target // 4 bytes.
12360+ // L_not:
12361+ //
12362+ // These instructions don't exist in the actual instruction stream, so we need to fake them
12363+ // up to display them.
12364+ emitDispLargeJmp(id, isNew, doffs, asmfm, offset, pCode, sz, ig);
12365+ }
12366+ else
12367+ {
12368+ emitDispInsHelp(id, isNew, doffs, asmfm, offset, pCode, sz, ig);
12369+ }
12370+ }
12371+
1225912372//--------------------------------------------------------------------
12260- // emitDispIns : Dump the given instruction to jitstdout.
12373+ // emitDispInsHelp : Dump the given instruction to jitstdout.
1226112374//
1226212375// Arguments:
1226312376// id - The instruction
@@ -12272,7 +12385,7 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz)
1227212385// sz - The size of the instruction, used to display the encoded bytes.
1227312386// ig - The instruction group containing the instruction.
1227412387//
12275- void emitter::emitDispIns (
12388+ void emitter::emitDispInsHelp (
1227612389 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
1227712390{
1227812391 if (EMITVERBOSE)
@@ -12284,7 +12397,9 @@ void emitter::emitDispIns(
1228412397 }
1228512398
1228612399 if (pCode == NULL)
12400+ {
1228712401 sz = 0;
12402+ }
1228812403
1228912404 if (!isNew && !asmfm && sz)
1229012405 {
@@ -12394,31 +12509,43 @@ void emitter::emitDispIns(
1239412509 break;
1239512510
1239612511 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
12512+ case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
12513+ {
1239712514 assert(insOptsNone(id->idInsOpt()));
1239812515 emitDispReg(id->idReg1(), size, true);
12399- if (id->idIsBound())
12516+
12517+ if (fmt == IF_BI_1B)
1240012518 {
12401- emitPrintLabel(id->idAddr()->iiaIGlabel );
12519+ emitDispImm(emitGetInsSC(id), true );
1240212520 }
12403- else
12521+
12522+ if (id->idAddr()->iiaHasInstrCount())
1240412523 {
12405- printf("L_M%03u_" FMT_BB, emitComp->compMethodID, id->idAddr()->iiaBBlabel->bbNum);
12406- }
12407- break;
12524+ int instrCount = id->idAddr()->iiaGetInstrCount();
1240812525
12409- case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
12410- assert(insOptsNone(id->idInsOpt()));
12411- emitDispReg(id->idReg1(), size, true);
12412- emitDispImm(emitGetInsSC(id), true);
12413- if (id->idIsBound())
12526+ if (ig == nullptr)
12527+ {
12528+ printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
12529+ }
12530+ else
12531+ {
12532+ unsigned insNum = emitFindInsNum(ig, id);
12533+ UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
12534+ UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
12535+ ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
12536+ printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
12537+ }
12538+ }
12539+ else if (id->idIsBound())
1241412540 {
1241512541 emitPrintLabel(id->idAddr()->iiaIGlabel);
1241612542 }
1241712543 else
1241812544 {
1241912545 printf("L_M%03u_" FMT_BB, emitComp->compMethodID, id->idAddr()->iiaBBlabel->bbNum);
1242012546 }
12421- break;
12547+ }
12548+ break;
1242212549
1242312550 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
1242412551 assert(insOptsNone(id->idInsOpt()));
0 commit comments