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