33#include " mainwindow.h"
44
55#include < QtWidgets/QApplication>
6+ #include < QStringView>
7+ #include < QLatin1StringView>
8+
9+ #include < algorithm>
10+ #include < array>
11+
12+
13+ using namespace Qt ::StringLiterals;
14+
15+ namespace {
16+ inline constexpr std::array controlFlowMnemonics {
17+ " CALL" _L1, " DJNZ" _L1, " JP" _L1, " JR" _L1, " RET" _L1, " RETI" _L1, " RETN" _L1, " RST" _L1
18+ };
19+
20+ inline constexpr std::array noTargetMnemonics {
21+ " RET" _L1, " RETI" _L1, " RETN" _L1
22+ };
23+
24+ inline constexpr std::array reservedTokens {
25+ " A" _L1, " B" _L1, " C" _L1, " D" _L1, " E" _L1, " H" _L1, " L" _L1, " I" _L1, " R" _L1,
26+ " AF" _L1, " BC" _L1, " DE" _L1, " HL" _L1, " SP" _L1,
27+ " IX" _L1, " IY" _L1, " IXH" _L1, " IXL" _L1,
28+ " IYH" _L1, " IYL" _L1, " MB" _L1,
29+ " NZ" _L1, " Z" _L1, " NC" _L1, " C" _L1,
30+ " PO" _L1, " PE" _L1, " P" _L1, " M" _L1
31+ };
32+ }
633
734DataWidget::DataWidget (QWidget *parent) : QPlainTextEdit{parent} {
835 moveable = false ;
@@ -143,6 +170,9 @@ AsmHighlighter::AsmHighlighter(QTextDocument *parent) : QSyntaxHighlighter(paren
143170
144171 mnemonicFormat.setForeground (QColor (darkMode ? " darkorange" : " darkblue" ));
145172
173+ controlFlowFormat.setForeground (QColor (" crimson" ));
174+ controlFlowTargetFormat.setForeground (QColor (" #dc795d" ));
175+
146176 symbolFormat.setFontWeight (disasm.bold_sym ? QFont::DemiBold : QFont::Normal);
147177 rule.pattern = QRegularExpression (" \\ b\\ w+\\ b" );
148178 rule.format = symbolFormat;
@@ -187,6 +217,18 @@ void AsmHighlighter::highlightBlock(const QString &text) {
187217 setFormat (match.capturedStart (4 ), match.capturedLength (4 ), breakPFormat);
188218 setFormat (match.capturedStart (5 ), match.capturedLength (5 ), bytesFormat);
189219 setFormat (match.capturedStart (6 ), match.capturedLength (6 ), mnemonicFormat);
220+
221+ const QString fullMnemonic = match.captured (6 );
222+ const QString primary = fullMnemonic.section (' .' , 0 , 0 ).toUpper ();
223+ const QStringView pv{primary};
224+
225+ const bool isControlFlow = std::any_of (controlFlowMnemonics.begin (), controlFlowMnemonics.end (),
226+ [&](const QLatin1StringView tok){ return pv == tok; });
227+
228+ if (isControlFlow) {
229+ setFormat (match.capturedStart (6 ), match.capturedLength (6 ), controlFlowFormat);
230+ }
231+
190232 foreach (const HighlightingRule &rule, highlightingRules) {
191233 QRegularExpressionMatchIterator iter = rule.pattern .globalMatch (text, match.capturedEnd ());
192234 while (iter.hasNext ()) {
@@ -196,5 +238,47 @@ void AsmHighlighter::highlightBlock(const QString &text) {
196238 }
197239 }
198240 }
241+
242+ if (!isControlFlow) {
243+ return ;
244+ }
245+
246+ if (std::any_of (noTargetMnemonics.begin (), noTargetMnemonics.end (),
247+ [&](const QLatin1StringView tok){ return pv == tok; })) {
248+ return ;
249+ }
250+
251+ const int operandStart = match.capturedEnd ();
252+ const QString operands = text.mid (operandStart);
253+
254+ // hex address patterns allowing optional +/ - after '$' for relative forms like $+5
255+ const QRegularExpression hexTargetRe (QStringLiteral (" \\ $[+\\ -]?[0-9A-Fa-f]+\\ b" ));
256+ QRegularExpressionMatchIterator hIt = hexTargetRe.globalMatch (operands);
257+ while (hIt.hasNext ()) {
258+ const auto m2 = hIt.next ();
259+ if (m2.hasMatch ()) {
260+ const int s = operandStart + m2.capturedStart ();
261+ const int l = m2.capturedLength ();
262+ setFormat (s, l, controlFlowTargetFormat);
263+ }
264+ }
265+
266+ // equate/label tokens (exclude registers and condition codes)
267+ const QRegularExpression labelRe (QStringLiteral (" \\ b[._A-Za-z][._A-Za-z0-9]*\\ b" ));
268+
269+ QRegularExpressionMatchIterator lIt = labelRe.globalMatch (operands);
270+ while (lIt.hasNext ()) {
271+ const auto m3 = lIt.next ();
272+ if (m3.hasMatch ()) {
273+ const QString tok = m3.captured ().toUpper ();
274+ if (std::any_of (reservedTokens.begin (), reservedTokens.end (),
275+ [&](const QLatin1StringView t){ return tok == t; })) {
276+ continue ;
277+ }
278+ const int start = operandStart + m3.capturedStart ();
279+ const int len = m3.capturedLength ();
280+ setFormat (start, len, controlFlowTargetFormat);
281+ }
282+ }
199283 }
200- }
284+ }
0 commit comments