19 Commits
Author SHA1 Message Date
chrisly42 954f42bf63 Tweaking for M68kRegisterFlowDocumentationProvider regarding colors, formatting and abbreviated documentation on hover. Prepared next release. 2021-08-03 07:59:47 +02:00
chrisly42 94001c8b87 Added explicit IndexRegister-PSI-Element. Major rework to support new DocumentationProvider on registers.
When asking for documentation on registers, a code flow analysis is done.
2021-08-02 20:54:30 +02:00
chrisly42 55403f89a6 Added a few tests for M68kSyntaxInspection. 2021-08-02 10:07:25 +02:00
chrisly42 7744b589d4 Added support for movem with register list crossing from data to address (e.g. d0-a6) as found in p61a source. 2021-08-02 09:43:42 +02:00
chrisly42 19e3b519db Bugfix: Macro definitions with colons and without space supported (as found in P61a source). 2021-08-02 09:41:51 +02:00
chrisly42 587b284d25 Fix in movem ISA (supports pc relative if first parameter). Also, single registers must also work (often optimized by the assembler). Increased default max macro parsing length to 250 lines. 2021-08-02 09:41:51 +02:00
chrisly42 719460ebfe Minor code refactoring. 2021-08-01 20:02:36 +02:00
chrisly42 44a4721d77 Added names for Adressing Modes.
Added Documentation Provider for symbol definitions (shows assigned declaration).
Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
Work in progress for Register Flow Documentation Provider.
New minimum required version of IDE is now 2020.3.
2021-08-01 19:51:42 +02:00
chrisly42 09a4e62c7c Bugfix: Interpretation of register lists was wrong in BNF.
Massively extended M68kIsa with description on register modifications (not yet used in production code).
Changed BNF for additional AddressingMode interfaces.
2021-08-01 10:08:01 +02:00
chrisly42 ce3cdbbed6 Bugfix: Uppercase hexadecimal literals were not parsed (JFlex bug?) 2021-07-31 14:12:58 +02:00
chrisly42 27b7593de8 Added several missing assembler directives (opt, machine, etc.) 2021-07-31 14:04:18 +02:00
chrisly42 3aeb415974 Massively reworked and extended ISA-Description class.
Added inspection to validate the correctness of a MC68000 instruction regarding operation size and address modes.
2021-07-31 13:56:07 +02:00
chrisly42 128330d2c7 Added Structure View filters for Symbols, Macros and Labels. 2021-07-30 15:25:48 +02:00
chrisly42 ef900e9c19 Added LICENSE.TXT, changed build.gradle to 2021.2 and added new build to plugin verification. Minor change to README.md regarding caching of coveralls badge. 2021-07-30 14:05:37 +02:00
chrisly42 8ea70f0dfa Docs update. Prepared next release. 2021-07-28 08:00:09 +02:00
chrisly42 fa1ef0b3d5 Reduced lexer code by combining state rules. Removed one rule, that seemed to be wrong. 2021-07-27 20:27:58 +02:00
chrisly42 3de9e9eba2 Restored compatibility with IDEs versions < 2021.1. Added PluginVerifier to build.gradle. 2021-07-27 17:46:11 +02:00
chrisly42 25450a9bf8 Macro definitions are now word and indexed, macro calls reference to definition.
Macro definition refactoring and find usages support.
Structural View also shows macro definitions.
Missing REPT and ENDR assembler directives added.
Changed or added some icons at various places.
Reference search for global labels and symbols now uses stub index.
2021-07-27 16:34:49 +02:00
chrisly42 6e683eb6a0 Started working on macro support. Macro-Definition are now plain, unparsed lines. Added Syntax-Highlighter options. 2021-07-27 12:42:26 +02:00
128 changed files with 4657 additions and 1309 deletions
+13
View File
@@ -0,0 +1,13 @@
Copyright 2021 Chris Hodges <chrisly@platon42.de>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+39 -12
View File
@@ -1,4 +1,4 @@
# MC68000 Assembly Language Plugin [![Build Status](https://travis-ci.com/chrisly42/mc68000-asm-plugin.svg?branch=main)](https://travis-ci.com/chrisly42/mc68000-asm-plugin) [![Coverage Status](https://coveralls.io/repos/github/chrisly42/mc68000-asm-plugin/badge.svg?branch=main)](https://coveralls.io/github/chrisly42/mc68000-asm-plugin?branch=main)
# MC68000 Assembly Language Plugin [![Build Status](https://travis-ci.com/chrisly42/mc68000-asm-plugin.svg?branch=main)](https://travis-ci.com/chrisly42/mc68000-asm-plugin) [![Coverage Status](https://coveralls.io/repos/github/chrisly42/mc68000-asm-plugin/badge.svg?branch=main&kill_cache=1)](https://coveralls.io/github/chrisly42/mc68000-asm-plugin?branch=main)
_MC68000 Assembly Language Plugin_ is plugin for Jetbrains IDEs (CLion, IntelliJ, etc.).
@@ -19,40 +19,42 @@ awesome features and is pretty advanced. Check it out. You can install both plug
Big kudos to Yann -- a few features were _inspired_ by his code.
My plugin, on the other hand, is still pretty basic and is the result of about a week's effort. I released a really early first version it because I think
My plugin, on the other hand, is still pretty basic and is the result of about two weeks of work. I released a really early first version it because I think
it's "good enough" to get started, and I can return to demo coding with its current state.
## Features
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
- Inspection for validating the syntax the 68000 ISA.
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
- Mnemonics code completion
- Symbols / Labels code completion
- References / Refactoring support for local and global labels, and symbol assignments.
- Symbols / Labels / Macros code completion
- References / Refactoring support for local and global labels, symbol assignments, and macros.
- Simple register usage flow (hover over register or press F1 for full flow)
- Brace matching
- Quote handler
- Goto Symbol support
- Structure view
- Documentation provider for symbol definitions and mnemonics (listing available addressing modes etc.).
## Known issues
- No referencing of macro invocations and macro definitions.
- `Find Usages` always shows _"Unclassified"_ though it shouldn't.
- Macro definitions may cause syntax errors when using backslash arguments.
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
- Macro invocations are not yet evaluated, thus no referencing to symbols defined via macros (e.g. `STRUCT`).
- No support for includes. Scoping is for global symbols and labels is currently the whole project.
- No support for register replacement (e.g. registers replaced by `EQUR` or `EQURL` will cause syntax errors)
- While the Lexer supports the -spaces option (where a space introduces a comment), this cannot be configured yet.
- While the Lexer supports the -spaces option (where a space introduces a comment), this cannot be configured yet (default is off).
- No support for other processor instructions, FPU or 68020+ address modes.
- No semantic checking for allowed address modes or data widths yet.
- Unit Test coverage is not as good as it could be (ahem).
- `opt` keyword needs special treatment and will currently show a parsing error
- Missing but planned features:
- Macro definition and evaluation on invocation
- Macro evaluation on invocation
- Folding
- Semantic inspections
- Quick fixes
- Formatter + Code Style Settings
- Register use analysis (but this only makes sense after macro evaluation)
- Cycle counting
## Recommendations
@@ -69,11 +71,36 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
## Changelog
### V0.4 (03-Aug-21)
- Notice: Due to major new API use, this plugin no longer works on IDEs >=2019.3.1, but rather requires >=2020.3.
- Enhancement: Added Structure View filters.
- New: Added inspection to validate the correctness of a MC68000 instruction regarding operation size and address modes.
- Bugfix: Added several missing assembler directives (`opt`, `machine`, etc.).
- Bugfix: Uppercase hexadecimal literals were not parsed (JFlex bug?).
- Bugfix: Interpretation of register lists was wrong in BNF.
- New: Added Documentation Provider for symbol definitions (shows assigned declaration).
- New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
- Bugfix: Macro definitions with colons and without space supported (as found in P61a source).
- New: When asking for documentation on registers, a code flow analysis is done. Cool stuff!
### V0.3 (28-Jul-21)
- Enhancement: Macro contents are no longer parsed, added syntax highlighting options for macros.
- Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
- New: Macro definition refactoring and find usages support.
- Enhancement: Structural View also shows macro definitions.
- Bugfix: Missing REPT and ENDR assembler directives added.
- Cosmetics: Changed or added some icons at various places.
- Performance: Reference search for global labels and symbols now uses stub index.
- Compatibility: Restored compatibility with IDE versions < 2021.1.
- Performance: Optimized lexer.
### V0.2 (27-Jul-21)
- Cosmetics: Added (same) icon for plugin as for file type.
- Performance improvement: Use Word-Index for global labels and symbols instead of iterating over the file.
- Performance improvement: Use Stub-Index for global labels and symbols.
- Performance: Use Word-Index for global labels and symbols instead of iterating over the file.
- Performance: Use Stub-Index for global labels and symbols.
- Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
- Enhancement: Registers are now offered for code completion, making editing less annoying.
+42 -10
View File
@@ -7,7 +7,7 @@ plugins {
}
group = 'de.platon42'
version = '0.2'
version = '0.4'
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
@@ -21,7 +21,7 @@ repositories {
*/
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
testImplementation "org.assertj:assertj-core:3.20.2"
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0-M1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
@@ -31,7 +31,10 @@ dependencies {
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += "-Xjvm-default=all"
}
}
compileTestKotlin {
@@ -39,25 +42,54 @@ compileTestKotlin {
}
intellij {
setVersion("2021.1.3") // LATEST-EAP-SNAPSHOT
setVersion("2021.2") // LATEST-EAP-SNAPSHOT
setUpdateSinceUntilBuild(false)
// setPlugins(["com.intellij.java"])
}
runPluginVerifier {
ideVersions = ["IC-203.6682.168", "IC-212.4746.92", // 2020.3 - 2021.2
"CL-203.5981.166", "CL-203.8084.11", // 2020.3
"CL-211.6693.114", "CL-211.7628.27", // 2021.1
"CL-212.4746.93"] // 2021.2
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea"
}
patchPluginXml {
setChangeNotes("""
<h4>V0.4 (03-Aug-21)</h4>
<ul>
<li>Notice: Due to major new API use, this plugin no longer works on IDEs >=2019.3.1, but rather requires >=2020.3.
<li>Enhancement: Added Structure View filters.
<li>New: Added inspection to validate the correctness of a MC68000 instruction regarding operation size and address modes.
<li>Bugfix: Added several missing assembler directives (opt, machine, etc.).
<li>Bugfix: Uppercase hexadecimal literals were not parsed (JFlex bug?).
<li>Bugfix: Interpretation of register lists was wrong in BNF.
<li>New: Added Documentation Provider for symbol definitions (shows assigned declaration).
<li>New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information).
<li>Bugfix: Macro definitions with colons and without space supported (as found in P61a source).
<li>New: When asking for documentation on registers, a code flow analysis is done. Cool stuff!
</ul>
<h4>V0.3 (28-Jul-21)</h4>
<ul>
<li>Enhancement: Macro contents are no longer parsed, added syntax highlighting options for macros.
<li>Enhancement: Macro definitions are now word and stub indexed, macro calls reference to definition.
<li>New: Macro definition refactoring and find usages support.
<li>Enhancement: Structural View also shows macro definitions.
<li>Bugfix: Missing REPT and ENDR assembler directives added.
<li>Cosmetics: Changed or added some icons at various places.
<li>Performance: Reference search for global labels and symbols now uses stub index.
<li>Compatibility: Restored compatibility with IDE versions < 2021.1.
<li>Performance: Optimized lexer.
</ul>
<h4>V0.2 (27-Jul-21)</h4>
<ul>
<li>Cosmetics: Added (same) icon for plugin as for file type.
<li>Performance improvement: Use Word-Index for global labels and symbols instead of iterating over the file.
<li>Performance improvement: Use Stub-Index for global labels and symbols.
<li>Performance: Use Word-Index for global labels and symbols instead of iterating over the file.
<li>Performance: Use Stub-Index for global labels and symbols.
<li>Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
<li>Enhancement: Registers are now offered for code completion, making editing less annoying.
</ul>
<h4>V0.1 (20-Jul-21)</h4>
<ul>
<li>Initial public release.
</ul>
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
""")
}
File diff suppressed because it is too large Load Diff
@@ -211,7 +211,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
// ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR IndexRegister ROUND_R
public static boolean AddressRegisterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false;
if (!nextTokenIsFast(b, ROUND_L)) return false;
@@ -221,8 +221,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_1(b, l + 1);
r = r && AddressRegister(b, l + 1);
r = r && consumeToken(b, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1);
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_5(b, l + 1);
r = r && IndexRegister(b, l + 1);
r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null);
return r;
@@ -246,15 +245,8 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r;
}
// DataWidth?
private static boolean AddressRegisterIndirectWithIndexNewAddressingMode_5(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode_5")) return false;
DataWidth(b, l + 1);
return true;
}
/* ********************************************************** */
// expr? ROUND_L AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
// expr? ROUND_L AddressRegister SEPARATOR IndexRegister ROUND_R
public static boolean AddressRegisterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false;
boolean r;
@@ -263,8 +255,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
r = r && consumeToken(b, ROUND_L);
r = r && AddressRegister(b, l + 1);
r = r && consumeToken(b, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1);
r = r && AddressRegisterIndirectWithIndexOldAddressingMode_5(b, l + 1);
r = r && IndexRegister(b, l + 1);
r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null);
return r;
@@ -277,13 +268,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// DataWidth?
private static boolean AddressRegisterIndirectWithIndexOldAddressingMode_5(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode_5")) return false;
DataWidth(b, l + 1);
return true;
}
/* ********************************************************** */
// OPSIZE_W|OPSIZE_L
public static boolean AddressSize(PsiBuilder b, int l) {
@@ -364,12 +348,12 @@ public class M68kParser implements PsiParser, LightPsiParser {
// MNEMONIC OperandSize?
public static boolean AsmOp(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "AsmOp")) return false;
if (!nextTokenIs(b, MNEMONIC)) return false;
if (!nextTokenIs(b, "<mnemonic>", MNEMONIC)) return false;
boolean r;
Marker m = enter_section_(b);
Marker m = enter_section_(b, l, _NONE_, ASM_OP, "<mnemonic>");
r = consumeToken(b, MNEMONIC);
r = r && AsmOp_1(b, l + 1);
exit_section_(b, m, ASM_OP, r);
exit_section_(b, l, m, r, false, null);
return r;
}
@@ -547,11 +531,30 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r;
}
/* ********************************************************** */
// DataOrAddressRegister DataWidth?
public static boolean IndexRegister(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "IndexRegister")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, INDEX_REGISTER, "<index register>");
r = DataOrAddressRegister(b, l + 1);
r = r && IndexRegister_1(b, l + 1);
exit_section_(b, l, m, r, false, null);
return r;
}
// DataWidth?
private static boolean IndexRegister_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "IndexRegister_1")) return false;
DataWidth(b, l + 1);
return true;
}
/* ********************************************************** */
// AsmInstruction | MacroCall
static boolean Instruction(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "Instruction")) return false;
if (!nextTokenIs(b, "", MACRO_INVOKATION, MNEMONIC)) return false;
if (!nextTokenIs(b, "", MACRO_INVOCATION, MNEMONIC)) return false;
boolean r;
r = AsmInstruction(b, l + 1);
if (!r) r = MacroCall(b, l + 1);
@@ -638,13 +641,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// MACRO_INVOKATION PlainOperands?
// MACRO_INVOCATION PlainOperands?
public static boolean MacroCall(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroCall")) return false;
if (!nextTokenIs(b, MACRO_INVOKATION)) return false;
if (!nextTokenIs(b, MACRO_INVOCATION)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_INVOKATION);
r = consumeToken(b, MACRO_INVOCATION);
r = r && MacroCall_1(b, l + 1);
exit_section_(b, m, MACRO_CALL, r);
return r;
@@ -657,6 +660,97 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
/* ********************************************************** */
// ((MacroNameDefinition COLON? MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG
public static boolean MacroDefinition(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition")) return false;
if (!nextTokenIs(b, "<macro definition>", MACRO_NAME, MACRO_TAG)) return false;
boolean r, p;
Marker m = enter_section_(b, l, _NONE_, MACRO_DEFINITION, "<macro definition>");
r = MacroDefinition_0(b, l + 1);
p = r; // pin = 1
r = r && report_error_(b, MacroDefinition_1(b, l + 1));
r = p && consumeToken(b, MACRO_END_TAG) && r;
exit_section_(b, l, m, r, p, null);
return r || p;
}
// (MacroNameDefinition COLON? MACRO_TAG)|(MACRO_TAG MacroNameDefinition)
private static boolean MacroDefinition_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = MacroDefinition_0_0(b, l + 1);
if (!r) r = MacroDefinition_0_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// MacroNameDefinition COLON? MACRO_TAG
private static boolean MacroDefinition_0_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = MacroNameDefinition(b, l + 1);
r = r && MacroDefinition_0_0_1(b, l + 1);
r = r && consumeToken(b, MACRO_TAG);
exit_section_(b, m, null, r);
return r;
}
// COLON?
private static boolean MacroDefinition_0_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0_0_1")) return false;
consumeToken(b, COLON);
return true;
}
// MACRO_TAG MacroNameDefinition
private static boolean MacroDefinition_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_0_1")) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_TAG);
r = r && MacroNameDefinition(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// MacroPlainLine*
private static boolean MacroDefinition_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroDefinition_1")) return false;
while (true) {
int c = current_position_(b);
if (!MacroPlainLine(b, l + 1)) break;
if (!empty_element_parsed_guard_(b, "MacroDefinition_1", c)) break;
}
return true;
}
/* ********************************************************** */
// MACRO_NAME
public static boolean MacroNameDefinition(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroNameDefinition")) return false;
if (!nextTokenIs(b, MACRO_NAME)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_NAME);
exit_section_(b, m, MACRO_NAME_DEFINITION, r);
return r;
}
/* ********************************************************** */
// MACRO_LINE
public static boolean MacroPlainLine(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "MacroPlainLine")) return false;
if (!nextTokenIs(b, MACRO_LINE)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, MACRO_LINE);
exit_section_(b, m, MACRO_PLAIN_LINE, r);
return r;
}
/* ********************************************************** */
// OPSIZE_BS|OPSIZE_W|OPSIZE_L
public static boolean OperandSize(PsiBuilder b, int l) {
@@ -671,19 +765,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// STRINGLIT (SEPARATOR STRINGLIT)*
// (expr|AddressingMode) (SEPARATOR (expr|AddressingMode))*
static boolean PlainOperands(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands")) return false;
if (!nextTokenIs(b, STRINGLIT)) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeToken(b, STRINGLIT);
r = PlainOperands_0(b, l + 1);
r = r && PlainOperands_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// (SEPARATOR STRINGLIT)*
// expr|AddressingMode
private static boolean PlainOperands_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_0")) return false;
boolean r;
r = expr(b, l + 1, -1);
if (!r) r = AddressingMode(b, l + 1);
return r;
}
// (SEPARATOR (expr|AddressingMode))*
private static boolean PlainOperands_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1")) return false;
while (true) {
@@ -694,16 +796,26 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// SEPARATOR STRINGLIT
// SEPARATOR (expr|AddressingMode)
private static boolean PlainOperands_1_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = consumeTokens(b, 0, SEPARATOR, STRINGLIT);
r = consumeToken(b, SEPARATOR);
r = r && PlainOperands_1_0_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// expr|AddressingMode
private static boolean PlainOperands_1_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "PlainOperands_1_0_1")) return false;
boolean r;
r = expr(b, l + 1, -1);
if (!r) r = AddressingMode(b, l + 1);
return r;
}
/* ********************************************************** */
// Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
// PreprocessorOperands?
@@ -829,7 +941,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// ROUND_L (expr SEPARATOR)? PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
// ROUND_L (expr SEPARATOR)? PC SEPARATOR IndexRegister ROUND_R
public static boolean ProgramCounterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false;
if (!nextTokenIsFast(b, ROUND_L)) return false;
@@ -838,8 +950,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
r = consumeTokenFast(b, ROUND_L);
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1);
r = r && consumeTokens(b, 0, PC, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1);
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_5(b, l + 1);
r = r && IndexRegister(b, l + 1);
r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null);
return r;
@@ -863,23 +974,15 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r;
}
// DataWidth?
private static boolean ProgramCounterIndirectWithIndexNewAddressingMode_5(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode_5")) return false;
DataWidth(b, l + 1);
return true;
}
/* ********************************************************** */
// expr? ROUND_L PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
// expr? ROUND_L PC SEPARATOR IndexRegister ROUND_R
public static boolean ProgramCounterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>");
r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1);
r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR);
r = r && DataOrAddressRegister(b, l + 1);
r = r && ProgramCounterIndirectWithIndexOldAddressingMode_5(b, l + 1);
r = r && IndexRegister(b, l + 1);
r = r && consumeToken(b, ROUND_R);
exit_section_(b, l, m, r, false, null);
return r;
@@ -892,13 +995,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// DataWidth?
private static boolean ProgramCounterIndirectWithIndexOldAddressingMode_5(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode_5")) return false;
DataWidth(b, l + 1);
return true;
}
/* ********************************************************** */
// CURRENT_PC_SYMBOL
public static boolean ProgramCounterReference(PsiBuilder b, int l) {
@@ -925,27 +1021,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// (DataOrAddressRegister|RegisterRange) ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
// (RegisterRange|DataOrAddressRegister) (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
public static boolean RegisterListAddressingMode(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterListAddressingMode")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, REGISTER_LIST_ADDRESSING_MODE, "<AddressingMode>");
Marker m = enter_section_(b, l, _NONE_, REGISTER_LIST_ADDRESSING_MODE, "<register list>");
r = RegisterListAddressingMode_0(b, l + 1);
r = r && RegisterListAddressingMode_1(b, l + 1);
exit_section_(b, l, m, r, false, null);
return r;
}
// DataOrAddressRegister|RegisterRange
// RegisterRange|DataOrAddressRegister
private static boolean RegisterListAddressingMode_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterListAddressingMode_0")) return false;
boolean r;
r = DataOrAddressRegister(b, l + 1);
if (!r) r = RegisterRange(b, l + 1);
r = RegisterRange(b, l + 1);
if (!r) r = DataOrAddressRegister(b, l + 1);
return r;
}
// ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
// (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
private static boolean RegisterListAddressingMode_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1")) return false;
while (true) {
@@ -956,44 +1052,71 @@ public class M68kParser implements PsiParser, LightPsiParser {
return true;
}
// (OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange)
// OP_AR_DIV (RegisterRange|DataOrAddressRegister)
private static boolean RegisterListAddressingMode_1_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = RegisterListAddressingMode_1_0_0(b, l + 1);
r = consumeTokenFast(b, OP_AR_DIV);
r = r && RegisterListAddressingMode_1_0_1(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// OP_AR_DIV|OP_MINUS
private static boolean RegisterListAddressingMode_1_0_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0_0")) return false;
boolean r;
r = consumeTokenFast(b, OP_AR_DIV);
if (!r) r = consumeTokenFast(b, OP_MINUS);
return r;
}
// DataOrAddressRegister|RegisterRange
// RegisterRange|DataOrAddressRegister
private static boolean RegisterListAddressingMode_1_0_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0_1")) return false;
boolean r;
r = DataOrAddressRegister(b, l + 1);
if (!r) r = RegisterRange(b, l + 1);
r = RegisterRange(b, l + 1);
if (!r) r = DataOrAddressRegister(b, l + 1);
return r;
}
/* ********************************************************** */
// DataOrAddressRegister OP_MINUS DataOrAddressRegister
static boolean RegisterRange(PsiBuilder b, int l) {
// (DataRegister OP_MINUS DataRegister) | (AddressRegister OP_MINUS AddressRegister) | (DataRegister OP_MINUS AddressRegister)
public static boolean RegisterRange(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterRange")) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, REGISTER_RANGE, "<register range>");
r = RegisterRange_0(b, l + 1);
if (!r) r = RegisterRange_1(b, l + 1);
if (!r) r = RegisterRange_2(b, l + 1);
exit_section_(b, l, m, r, false, null);
return r;
}
// DataRegister OP_MINUS DataRegister
private static boolean RegisterRange_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterRange_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = DataOrAddressRegister(b, l + 1);
r = DataRegister(b, l + 1);
r = r && consumeToken(b, OP_MINUS);
r = r && DataOrAddressRegister(b, l + 1);
r = r && DataRegister(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// AddressRegister OP_MINUS AddressRegister
private static boolean RegisterRange_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterRange_1")) return false;
boolean r;
Marker m = enter_section_(b);
r = AddressRegister(b, l + 1);
r = r && consumeToken(b, OP_MINUS);
r = r && AddressRegister(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// DataRegister OP_MINUS AddressRegister
private static boolean RegisterRange_2(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "RegisterRange_2")) return false;
boolean r;
Marker m = enter_section_(b);
r = DataRegister(b, l + 1);
r = r && consumeToken(b, OP_MINUS);
r = r && AddressRegister(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
@@ -1048,13 +1171,13 @@ public class M68kParser implements PsiParser, LightPsiParser {
}
/* ********************************************************** */
// !<<eof>> statement (<<eof>>|EOL)
// !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
static boolean line(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "line")) return false;
boolean r;
Marker m = enter_section_(b);
r = line_0(b, l + 1);
r = r && statement(b, l + 1);
r = r && line_1(b, l + 1);
r = r && line_2(b, l + 1);
exit_section_(b, m, null, r);
return r;
@@ -1070,6 +1193,17 @@ public class M68kParser implements PsiParser, LightPsiParser {
return r;
}
// MacroDefinition | statement
private static boolean line_1(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "line_1")) return false;
boolean r;
Marker m = enter_section_(b);
r = MacroDefinition(b, l + 1);
if (!r) r = statement(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// <<eof>>|EOL
private static boolean line_2(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "line_2")) return false;
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
public interface M68kAddressRegisterIndirectAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
@NotNull
M68kAddressRegister getAddressRegister();
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
public interface M68kAddressRegisterIndirectPostIncAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectPostIncAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
@NotNull
M68kAddressRegister getAddressRegister();
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
public interface M68kAddressRegisterIndirectPreDecAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectPreDecAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
@NotNull
M68kAddressRegister getAddressRegister();
@@ -3,12 +3,12 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
public interface M68kAddressRegisterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement {
@NotNull
M68kAddressRegister getAddressRegister();
@NotNull
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -3,12 +3,12 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
public interface M68kAddressRegisterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement {
@NotNull
M68kAddressRegister getAddressRegister();
@NotNull
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -4,18 +4,15 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement, M68kWithIndexRegister {
@NotNull
M68kAddressRegister getAddressRegister();
@Nullable
M68kDataWidth getDataWidth();
@NotNull
M68kRegister getRegister();
M68kIndexRegister getIndexRegister();
@Nullable
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -4,18 +4,15 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M68kAddressingMode {
public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement, M68kWithIndexRegister {
@NotNull
M68kAddressRegister getAddressRegister();
@Nullable
M68kDataWidth getDataWidth();
@NotNull
M68kRegister getRegister();
M68kIndexRegister getIndexRegister();
@Nullable
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -1,6 +1,7 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface M68kAsmOp extends M68kPsiElement {
@@ -8,4 +9,9 @@ public interface M68kAsmOp extends M68kPsiElement {
@Nullable
M68kOperandSize getOperandSize();
@NotNull
String getMnemonic();
int getOpSize();
}
@@ -0,0 +1,17 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface M68kIndexRegister extends M68kPsiElement {
@Nullable
M68kDataWidth getDataWidth();
@NotNull
M68kRegister getRegister();
boolean isLongWidth();
}
@@ -1,6 +1,19 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public interface M68kMacroCall extends M68kPsiElement {
@NotNull
List<M68kAddressingMode> getAddressingModeList();
@NotNull
List<M68kExpr> getExprList();
@NotNull
String getMacroName();
}
@@ -0,0 +1,29 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement;
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface M68kMacroDefinition extends M68kNamedElement, StubBasedPsiElement<M68kMacroDefinitionStub> {
@NotNull
M68kMacroNameDefinition getMacroNameDefinition();
@NotNull
List<M68kMacroPlainLine> getMacroPlainLineList();
@Nullable
String getName();
@NotNull
PsiElement setName(@NotNull String name);
@NotNull
PsiElement getNameIdentifier();
}
@@ -0,0 +1,6 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
public interface M68kMacroNameDefinition extends M68kPsiElement {
}
@@ -0,0 +1,6 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
public interface M68kMacroPlainLine extends M68kPsiElement {
}
@@ -3,4 +3,6 @@ package de.platon42.intellij.plugins.m68k.psi;
public interface M68kOperandSize extends M68kPsiElement {
int getSize();
}
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
public interface M68kProgramCounterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode {
public interface M68kProgramCounterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement {
@NotNull
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.Nullable;
public interface M68kProgramCounterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode {
public interface M68kProgramCounterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement {
@Nullable
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -4,15 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode {
@Nullable
M68kDataWidth getDataWidth();
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
@NotNull
M68kRegister getRegister();
M68kIndexRegister getIndexRegister();
@Nullable
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -4,15 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode {
@Nullable
M68kDataWidth getDataWidth();
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
@NotNull
M68kRegister getRegister();
M68kIndexRegister getIndexRegister();
@Nullable
M68kExpr getExpr();
M68kExpr getDisplacement();
}
@@ -1,13 +1,21 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import de.platon42.intellij.plugins.m68k.asm.Register;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
public interface M68kRegisterListAddressingMode extends M68kAddressingMode {
@NotNull
List<M68kRegister> getRegisterList();
@NotNull
List<M68kRegisterRange> getRegisterRangeList();
@NotNull
Set<Register> getRegisters();
}
@@ -0,0 +1,20 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface M68kRegisterRange extends M68kPsiElement {
@NotNull
List<M68kRegister> getRegisterList();
@NotNull
M68kRegister getStartRegister();
@Nullable
M68kRegister getEndRegister();
}
@@ -48,9 +48,13 @@ public interface M68kTypes {
IElementType EXPR = new M68kElementType("EXPR");
IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL");
IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA");
IElementType INDEX_REGISTER = new M68kElementType("INDEX_REGISTER");
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
IElementType MACRO_DEFINITION = M68kStubElementTypeFactory.stubFactory("MACRO_DEFINITION");
IElementType MACRO_NAME_DEFINITION = new M68kElementType("MACRO_NAME_DEFINITION");
IElementType MACRO_PLAIN_LINE = new M68kElementType("MACRO_PLAIN_LINE");
IElementType OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
IElementType PREPROCESSOR_DIRECTIVE = new M68kElementType("PREPROCESSOR_DIRECTIVE");
@@ -62,6 +66,7 @@ public interface M68kTypes {
IElementType REF_EXPR = new M68kElementType("REF_EXPR");
IElementType REGISTER = new M68kElementType("REGISTER");
IElementType REGISTER_LIST_ADDRESSING_MODE = new M68kElementType("REGISTER_LIST_ADDRESSING_MODE");
IElementType REGISTER_RANGE = new M68kElementType("REGISTER_RANGE");
IElementType SPECIAL_REGISTER = new M68kElementType("SPECIAL_REGISTER");
IElementType SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE = new M68kElementType("SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE");
IElementType STATEMENT = new M68kElementType("STATEMENT");
@@ -86,7 +91,11 @@ public interface M68kTypes {
IElementType HASH = new M68kTokenType("HASH");
IElementType HEXADECIMAL = new M68kTokenType("HEXADECIMAL");
IElementType LOCAL_LABEL_DEF = new M68kTokenType("LOCAL_LABEL_DEF");
IElementType MACRO_INVOKATION = new M68kTokenType("MACRO_INVOKATION");
IElementType MACRO_END_TAG = new M68kTokenType("MACRO_END_TAG");
IElementType MACRO_INVOCATION = new M68kTokenType("MACRO_INVOCATION");
IElementType MACRO_LINE = new M68kTokenType("MACRO_LINE");
IElementType MACRO_NAME = new M68kTokenType("MACRO_NAME");
IElementType MACRO_TAG = new M68kTokenType("MACRO_TAG");
IElementType MNEMONIC = new M68kTokenType("MNEMONIC");
IElementType OCTAL = new M68kTokenType("OCTAL");
IElementType OPSIZE_BS = new M68kTokenType("OPSIZE_BS");
@@ -204,12 +213,20 @@ public interface M68kTypes {
return new M68kGlobalLabelImpl(node);
} else if (type == IMMEDIATE_DATA) {
return new M68kImmediateDataImpl(node);
} else if (type == INDEX_REGISTER) {
return new M68kIndexRegisterImpl(node);
} else if (type == LITERAL_EXPR) {
return new M68kLiteralExprImpl(node);
} else if (type == LOCAL_LABEL) {
return new M68kLocalLabelImpl(node);
} else if (type == MACRO_CALL) {
return new M68kMacroCallImpl(node);
} else if (type == MACRO_DEFINITION) {
return new M68kMacroDefinitionImpl(node);
} else if (type == MACRO_NAME_DEFINITION) {
return new M68kMacroNameDefinitionImpl(node);
} else if (type == MACRO_PLAIN_LINE) {
return new M68kMacroPlainLineImpl(node);
} else if (type == OPERAND_SIZE) {
return new M68kOperandSizeImpl(node);
} else if (type == PAREN_EXPR) {
@@ -230,6 +247,8 @@ public interface M68kTypes {
return new M68kRefExprImpl(node);
} else if (type == REGISTER_LIST_ADDRESSING_MODE) {
return new M68kRegisterListAddressingModeImpl(node);
} else if (type == REGISTER_RANGE) {
return new M68kRegisterRangeImpl(node);
} else if (type == SPECIAL_REGISTER) {
return new M68kSpecialRegisterImpl(node);
} else if (type == SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE) {
@@ -20,30 +20,43 @@ public class M68kVisitor extends PsiElementVisitor {
public void visitAddressRegisterIndirectAddressingMode(@NotNull M68kAddressRegisterIndirectAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
}
public void visitAddressRegisterIndirectPostIncAddressingMode(@NotNull M68kAddressRegisterIndirectPostIncAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
}
public void visitAddressRegisterIndirectPreDecAddressingMode(@NotNull M68kAddressRegisterIndirectPreDecAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
}
public void visitAddressRegisterIndirectWithDisplacementNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementNewAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
// visitWithDisplacement(o);
}
public void visitAddressRegisterIndirectWithDisplacementOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementOldAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
// visitWithDisplacement(o);
}
public void visitAddressRegisterIndirectWithIndexNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexNewAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
// visitWithDisplacement(o);
// visitWithIndexRegister(o);
}
public void visitAddressRegisterIndirectWithIndexOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexOldAddressingMode o) {
visitAddressingMode(o);
// visitWithAddressRegisterIndirect(o);
// visitWithDisplacement(o);
// visitWithIndexRegister(o);
}
public void visitAddressSize(@NotNull M68kAddressSize o) {
@@ -86,6 +99,10 @@ public class M68kVisitor extends PsiElementVisitor {
visitAddressingMode(o);
}
public void visitIndexRegister(@NotNull M68kIndexRegister o) {
visitPsiElement(o);
}
public void visitLocalLabel(@NotNull M68kLocalLabel o) {
visitNamedElement(o);
}
@@ -94,6 +111,18 @@ public class M68kVisitor extends PsiElementVisitor {
visitPsiElement(o);
}
public void visitMacroDefinition(@NotNull M68kMacroDefinition o) {
visitNamedElement(o);
}
public void visitMacroNameDefinition(@NotNull M68kMacroNameDefinition o) {
visitPsiElement(o);
}
public void visitMacroPlainLine(@NotNull M68kMacroPlainLine o) {
visitPsiElement(o);
}
public void visitOperandSize(@NotNull M68kOperandSize o) {
visitPsiElement(o);
}
@@ -104,18 +133,24 @@ public class M68kVisitor extends PsiElementVisitor {
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
visitAddressingMode(o);
// visitWithDisplacement(o);
}
public void visitProgramCounterIndirectWithDisplacementOldAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementOldAddressingMode o) {
visitAddressingMode(o);
// visitWithDisplacement(o);
}
public void visitProgramCounterIndirectWithIndexNewAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexNewAddressingMode o) {
visitAddressingMode(o);
// visitWithDisplacement(o);
// visitWithIndexRegister(o);
}
public void visitProgramCounterIndirectWithIndexOldAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexOldAddressingMode o) {
visitAddressingMode(o);
// visitWithDisplacement(o);
// visitWithIndexRegister(o);
}
public void visitProgramCounterReference(@NotNull M68kProgramCounterReference o) {
@@ -130,6 +165,10 @@ public class M68kVisitor extends PsiElementVisitor {
visitAddressingMode(o);
}
public void visitRegisterRange(@NotNull M68kRegisterRange o) {
visitPsiElement(o);
}
public void visitSpecialRegister(@NotNull M68kSpecialRegister o) {
visitRegister(o);
}
@@ -35,7 +35,7 @@ public class M68kAddressRegisterIndirectWithDisplacementNewAddressingModeImpl ex
@Override
@NotNull
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
}
@@ -35,7 +35,7 @@ public class M68kAddressRegisterIndirectWithDisplacementOldAddressingModeImpl ex
@Override
@NotNull
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
}
@@ -31,21 +31,15 @@ public class M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl extends M
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
}
@Override
@Nullable
public M68kDataWidth getDataWidth() {
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
}
@Override
@NotNull
public M68kRegister getRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override
@Nullable
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
}
@@ -31,21 +31,15 @@ public class M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl extends M
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
}
@Override
@Nullable
public M68kDataWidth getDataWidth() {
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
}
@Override
@NotNull
public M68kRegister getRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override
@Nullable
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
}
@@ -7,6 +7,7 @@ import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp;
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize;
import de.platon42.intellij.plugins.m68k.psi.M68kPsiImplUtil;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,4 +34,15 @@ public class M68kAsmOpImpl extends ASTWrapperPsiElement implements M68kAsmOp {
return PsiTreeUtil.getChildOfType(this, M68kOperandSize.class);
}
@Override
@NotNull
public String getMnemonic() {
return M68kPsiImplUtil.getMnemonic(this);
}
@Override
public int getOpSize() {
return M68kPsiImplUtil.getOpSize(this);
}
}
@@ -0,0 +1,45 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class M68kIndexRegisterImpl extends ASTWrapperPsiElement implements M68kIndexRegister {
public M68kIndexRegisterImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitIndexRegister(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
@Override
@Nullable
public M68kDataWidth getDataWidth() {
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
}
@Override
@NotNull
public M68kRegister getRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
}
@Override
public boolean isLongWidth() {
return M68kPsiImplUtil.isLongWidth(this);
}
}
@@ -1,14 +1,15 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import org.jetbrains.annotations.NotNull;
public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacroCall {
import java.util.List;
public class M68kMacroCallImpl extends M68kMacroCallMixin implements M68kMacroCall {
public M68kMacroCallImpl(@NotNull ASTNode node) {
super(node);
@@ -24,4 +25,22 @@ public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacro
else super.accept(visitor);
}
@Override
@NotNull
public List<M68kAddressingMode> getAddressingModeList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kAddressingMode.class);
}
@Override
@NotNull
public List<M68kExpr> getExprList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kExpr.class);
}
@Override
@NotNull
public String getMacroName() {
return M68kPsiImplUtil.getMacroName(this);
}
}
@@ -0,0 +1,66 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class M68kMacroDefinitionImpl extends M68kMacroDefinitionMixin implements M68kMacroDefinition {
public M68kMacroDefinitionImpl(@NotNull ASTNode node) {
super(node);
}
public M68kMacroDefinitionImpl(@NotNull M68kMacroDefinitionStub stub, @NotNull IStubElementType<?, ?> nodeType) {
super(stub, nodeType);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroDefinition(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
@Override
@NotNull
public M68kMacroNameDefinition getMacroNameDefinition() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kMacroNameDefinition.class));
}
@Override
@NotNull
public List<M68kMacroPlainLine> getMacroPlainLineList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kMacroPlainLine.class);
}
@Override
@Nullable
public String getName() {
return M68kPsiImplUtil.getName(this);
}
@Override
@NotNull
public PsiElement setName(@NotNull String name) {
return M68kPsiImplUtil.setName(this, name);
}
@Override
@NotNull
public PsiElement getNameIdentifier() {
return M68kPsiImplUtil.getNameIdentifier(this);
}
}
@@ -0,0 +1,27 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroNameDefinition;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
public class M68kMacroNameDefinitionImpl extends ASTWrapperPsiElement implements M68kMacroNameDefinition {
public M68kMacroNameDefinitionImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroNameDefinition(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
}
@@ -0,0 +1,27 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kMacroPlainLine;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
public class M68kMacroPlainLineImpl extends ASTWrapperPsiElement implements M68kMacroPlainLine {
public M68kMacroPlainLineImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitMacroPlainLine(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
}
@@ -5,6 +5,7 @@ import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize;
import de.platon42.intellij.plugins.m68k.psi.M68kPsiImplUtil;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
@@ -24,4 +25,9 @@ public class M68kOperandSizeImpl extends ASTWrapperPsiElement implements M68kOpe
else super.accept(visitor);
}
@Override
public int getSize() {
return M68kPsiImplUtil.getSize(this);
}
}
@@ -28,7 +28,7 @@ public class M68kProgramCounterIndirectWithDisplacementNewAddressingModeImpl ext
@Override
@NotNull
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
}
@@ -29,7 +29,7 @@ public class M68kProgramCounterIndirectWithDisplacementOldAddressingModeImpl ext
@Override
@Nullable
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
}
@@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import de.platon42.intellij.plugins.m68k.psi.M68kExpr;
import de.platon42.intellij.plugins.m68k.psi.M68kIndexRegister;
import de.platon42.intellij.plugins.m68k.psi.M68kProgramCounterIndirectWithIndexNewAddressingMode;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,21 +28,15 @@ public class M68kProgramCounterIndirectWithIndexNewAddressingModeImpl extends M6
else super.accept(visitor);
}
@Override
@Nullable
public M68kDataWidth getDataWidth() {
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
}
@Override
@NotNull
public M68kRegister getRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override
@Nullable
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
}
@@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.*;
import de.platon42.intellij.plugins.m68k.psi.M68kExpr;
import de.platon42.intellij.plugins.m68k.psi.M68kIndexRegister;
import de.platon42.intellij.plugins.m68k.psi.M68kProgramCounterIndirectWithIndexOldAddressingMode;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,21 +28,15 @@ public class M68kProgramCounterIndirectWithIndexOldAddressingModeImpl extends M6
else super.accept(visitor);
}
@Override
@Nullable
public M68kDataWidth getDataWidth() {
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
}
@Override
@NotNull
public M68kRegister getRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
public M68kIndexRegister getIndexRegister() {
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
}
@Override
@Nullable
public M68kExpr getExpr() {
public M68kExpr getDisplacement() {
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
}
@@ -4,12 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.M68kRegister;
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterListAddressingMode;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import de.platon42.intellij.plugins.m68k.asm.Register;
import de.platon42.intellij.plugins.m68k.psi.*;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Set;
public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl implements M68kRegisterListAddressingMode {
@@ -34,4 +34,16 @@ public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl i
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegister.class);
}
@Override
@NotNull
public List<M68kRegisterRange> getRegisterRangeList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegisterRange.class);
}
@Override
@NotNull
public Set<Register> getRegisters() {
return M68kPsiImplUtil.getRegisters(this);
}
}
@@ -0,0 +1,52 @@
// This is a generated file. Not intended for manual editing.
package de.platon42.intellij.plugins.m68k.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import de.platon42.intellij.plugins.m68k.psi.M68kRegister;
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterRange;
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class M68kRegisterRangeImpl extends ASTWrapperPsiElement implements M68kRegisterRange {
public M68kRegisterRangeImpl(@NotNull ASTNode node) {
super(node);
}
public void accept(@NotNull M68kVisitor visitor) {
visitor.visitRegisterRange(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
else super.accept(visitor);
}
@Override
@NotNull
public List<M68kRegister> getRegisterList() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegister.class);
}
@Override
@NotNull
public M68kRegister getStartRegister() {
List<M68kRegister> p1 = getRegisterList();
return p1.get(0);
}
@Override
@Nullable
public M68kRegister getEndRegister() {
List<M68kRegister> p1 = getRegisterList();
return p1.size() < 2 ? null : p1.get(1);
}
}
@@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
@JvmField
val INSTANCE = M68kFileElementType()
const val STUB_VERSION = 3
const val STUB_VERSION = 5
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
}
@@ -7,5 +7,8 @@ object M68kIcons {
val FILE = IconLoader.getIcon("/icons/FileType_m68k.svg", javaClass)
val LOCAL_LABEL = AllIcons.Nodes.AbstractMethod
val GLOBAL_LABEL = AllIcons.Nodes.Method
val SYMBOL_DEF = AllIcons.Nodes.Constant
val SYMBOL_DEF = AllIcons.Nodes.ClassInitializer
val MACRO_DEF = AllIcons.Nodes.MultipleTypeDefinitions
val REGISTER = AllIcons.Nodes.DataTables // AllIcons.Nodes.Record only available starting from 2020.1
val MNEMONIC = AllIcons.Nodes.C_protected
}
@@ -3,46 +3,56 @@ package de.platon42.intellij.plugins.m68k.asm
object AssemblerDirectives {
val dataDirectives: Set<String> = setOf(
"section", "pushsection", "popsection",
"bss", "bss_c", "bss_f",
"data", "data_c", "data_f",
"text", "cseg", "code", "code_c", "code_f",
"offset",
"section", "pushsection", "popsection",
"bss", "bss_c", "bss_f",
"data", "data_c", "data_f",
"text", "cseg", "code", "code_c", "code_f",
"offset",
"abs",
"db", "dw", "dl",
"dr.b", "dr.w", "dr.l",
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
"blk.b", "blk.w", "blk.l",
"ds", "ds.b", "ds.w", "ds.l",
"abs",
"db", "dw", "dl",
"dr.b", "dr.w", "dr.l",
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
"blk.b", "blk.w", "blk.l",
"ds", "ds.b", "ds.w", "ds.l",
"align", "even", "odd", "cnop", "long", "dphrase", "phrase", "qphrase",
"align", "even", "odd", "cnop", "long", "dphrase", "phrase", "qphrase",
"cargs", "comm", "comment",
"rsset", "clrfo", "clrso", "setfo", "setso"
"cargs", "comm", "comment",
"rsset", "clrfo", "clrso", "setfo", "setso"
)
val otherDirective: Set<String> = setOf(
"if",
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
"ifd", "ifnd", "ifmacrod", "ifmacrond",
//"iif" // not supported
"else", "endif", "endc",
"if",
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
"ifd", "ifnd", "ifmacrod", "ifmacrond",
//"iif" // not supported
"else", "endif", "endc",
"macro", "exitm", "mexit", "endm",
"rept", "endr",
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
"macro", "exitm", "mexit", "endm",
"reg", "equr", "equrl",
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
"incdir", "include", "incbin", "output",
"reg", "equr", "equrl",
"freg", "fequr", "fequrl",
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
"org",
"incdir", "include", "incbin", "output",
"assert", "fail", "print", "printt", "printv", "echo",
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
"org",
"inline", "einline",
"rem", "erem"
"assert", "fail", "print", "printt", "printv", "echo",
"inline", "einline",
"rem", "erem",
"machine", "mc68000", "mc68010", "mc68020", "mc68030", "mc68040", "mc68060",
"fpu",
"basereg", "endb", "far", "near", "initnear",
"opt"
)
}
@@ -9,6 +9,118 @@ enum class Machine {
MC68060
}
enum class Register(val regname: String, val num: Int) {
D0("d0", 0),
D1("d1", 1),
D2("d2", 2),
D3("d3", 3),
D4("d4", 4),
D5("d5", 5),
D6("d6", 6),
D7("d7", 7),
A0("a0", 0),
A1("a1", 1),
A2("a2", 2),
A3("a3", 3),
A4("a4", 4),
A5("a5", 5),
A6("a6", 6),
A7("a7", 7);
companion object {
private val NAME_TO_REG_MAP = values().associateBy { it.regname }.plus("sp" to A7)
fun getRegFromName(regname: String) = NAME_TO_REG_MAP[regname.lowercase()]!!
}
}
enum class AddressMode(val description: String, val syntax: String) {
DATA_REGISTER_DIRECT("data register direct", "Dn"),
ADDRESS_REGISTER_DIRECT("address register direct", "An"),
ADDRESS_REGISTER_INDIRECT("address register indirect", "(An)"),
ADDRESS_REGISTER_INDIRECT_POST_INC("address register indirect with postincrement", "(An)+"),
ADDRESS_REGISTER_INDIRECT_PRE_DEC("address register indirect with predecrement", "-(An)"),
ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT("address register indirect with displacement", "(d16,An)"),
PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT("program counter indirect with displacement", "(d16,PC)"),
ADDRESS_REGISTER_INDIRECT_WITH_INDEX("address register indirect with index", "(d8,An,Xn)"),
PROGRAM_COUNTER_INDIRECT_WITH_INDEX("program counter indirect with index", "(d8,PC,Xn)"),
SPECIAL_REGISTER_DIRECT("special register", "ccr|usp|vbr"),
REGISTER_LIST("register list", "list"),
IMMEDIATE_DATA("immediate", "#<xxx>"),
ABSOLUTE_ADDRESS("absolute short/long", "(xxx).w|l")
}
const val OP_UNSIZED = 0
const val OP_SIZE_B = 1
const val OP_SIZE_W = 2
const val OP_SIZE_L = 4
const val OP_SIZE_S = 8
const val OP_SIZE_BWL = (OP_SIZE_B or OP_SIZE_W or OP_SIZE_L)
const val OP_SIZE_WL = (OP_SIZE_W or OP_SIZE_L)
const val OP_SIZE_SBW = (OP_SIZE_B or OP_SIZE_S or OP_SIZE_W)
const val RWM_OP_MASK = 0xfff
const val RWM_SIZE_MASK = 0x00e
const val RWM_SET_OPSIZE = 0x008
const val RWM_SET_B = 0x009
const val RWM_SET_W = 0x00b
const val RWM_SET_L = 0x00f
const val RWM_READ_OPSIZE = 0x800
const val RWM_READ_B = 0x900
const val RWM_READ_W = 0xb00
const val RWM_READ_L = 0xf00
const val RWM_MODIFY_OPSIZE = 0x880
const val RWM_MODIFY_B = 0x990
const val RWM_MODIFY_W = 0xbb0
const val RWM_MODIFY_L = 0xff0
const val RWM_OP1_SHIFT = 0
const val RWM_OP2_SHIFT = 12
const val RWM_READ_OP1_OPSIZE = RWM_READ_OPSIZE shl RWM_OP1_SHIFT
const val RWM_READ_OP1_B = RWM_READ_B shl RWM_OP1_SHIFT
const val RWM_READ_OP1_W = RWM_READ_W shl RWM_OP1_SHIFT
const val RWM_READ_OP1_L = RWM_READ_L shl RWM_OP1_SHIFT
const val RWM_MODIFY_OP1_OPSIZE = RWM_MODIFY_OPSIZE shl RWM_OP1_SHIFT
const val RWM_MODIFY_OP1_B = RWM_MODIFY_B shl RWM_OP1_SHIFT
const val RWM_MODIFY_OP1_W = RWM_MODIFY_W shl RWM_OP1_SHIFT
const val RWM_MODIFY_OP1_L = RWM_MODIFY_L shl RWM_OP1_SHIFT
const val RWM_SET_OP1_OPSIZE = RWM_SET_OPSIZE shl RWM_OP1_SHIFT
const val RWM_SET_OP1_B = RWM_SET_B shl RWM_OP1_SHIFT
const val RWM_SET_OP1_W = RWM_SET_W shl RWM_OP1_SHIFT
const val RWM_SET_OP1_L = RWM_SET_L shl RWM_OP1_SHIFT
const val RWM_READ_OP2_OPSIZE = RWM_READ_OPSIZE shl RWM_OP2_SHIFT
const val RWM_READ_OP2_B = RWM_READ_B shl RWM_OP2_SHIFT
const val RWM_READ_OP2_W = RWM_READ_W shl RWM_OP2_SHIFT
const val RWM_READ_OP2_L = RWM_READ_L shl RWM_OP2_SHIFT
const val RWM_MODIFY_OP2_OPSIZE = RWM_MODIFY_OPSIZE shl RWM_OP2_SHIFT
const val RWM_MODIFY_OP2_B = RWM_MODIFY_B shl RWM_OP2_SHIFT
const val RWM_MODIFY_OP2_W = RWM_MODIFY_W shl RWM_OP2_SHIFT
const val RWM_MODIFY_OP2_L = RWM_MODIFY_L shl RWM_OP2_SHIFT
const val RWM_SET_OP2_OPSIZE = RWM_SET_OPSIZE shl RWM_OP2_SHIFT
const val RWM_SET_OP2_B = RWM_SET_B shl RWM_OP2_SHIFT
const val RWM_SET_OP2_W = RWM_SET_W shl RWM_OP2_SHIFT
const val RWM_SET_OP2_L = RWM_SET_L shl RWM_OP2_SHIFT
const val RWM_MODIFY_STACK = 0x1000000
data class AllowedAdrMode(
val op1: Set<AddressMode>? = null,
val op2: Set<AddressMode>? = null,
val size: Int = OP_SIZE_BWL,
val specialReg: String? = null,
val modInfo: Int = 0
)
data class IsaData(
val mnemonic: String,
val description: String,
@@ -16,141 +128,602 @@ data class IsaData(
val altMnemonics: List<String> = emptyList(),
val conditionCodes: List<String> = emptyList(),
val id: String = mnemonic,
val opSize: String = "bWl",
val isPrivileged: Boolean = false,
val hasOps: Boolean = true
val hasOps: Boolean = true,
val modes: List<AllowedAdrMode> = listOf(AllowedAdrMode()),
)
object M68kIsa {
val conditionCodes =
listOf("cc", "ls", "cs", "lt", "eq", "mi", "f", "ne", "ge", "pl", "gt", "t", "hi", "vc", "le", "vs")
val conditionCodesBcc = conditionCodes.filterNot { it == "f" || it == "t" }
val isaData = listOf(
private val NO_OPS_UNSIZED = listOf(AllowedAdrMode(size = OP_UNSIZED))
private val ALL_68000_MODES = setOf(
AddressMode.DATA_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.IMMEDIATE_DATA,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
)
private val ALL_EXCEPT_IMMEDIATE_AND_PC_REL = setOf(
AddressMode.DATA_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS
)
private val ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL = setOf(
AddressMode.DATA_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS
)
private val ALL_EXCEPT_AREG_AND_IMMEDIATE = setOf(
AddressMode.DATA_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
)
private val ALL_EXCEPT_AREG = setOf(
AddressMode.DATA_REGISTER_DIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.IMMEDIATE_DATA,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
)
private val INDIRECT_MODES = setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS
)
private val AREG_ONLY = setOf(AddressMode.ADDRESS_REGISTER_DIRECT)
private val DREG_ONLY = setOf(AddressMode.DATA_REGISTER_DIRECT)
private val ADD_SUB_MODES = listOf(
AllowedAdrMode(ALL_EXCEPT_AREG, setOf(AddressMode.DATA_REGISTER_DIRECT), modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_DIRECT),
setOf(AddressMode.DATA_REGISTER_DIRECT),
OP_SIZE_WL,
modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE
),
AllowedAdrMode(setOf(AddressMode.DATA_REGISTER_DIRECT), INDIRECT_MODES, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
)
private val ASD_LSD_ROD_ROXD_MODES = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE),
)
private val BCHG_BCLR_BSET_MODES = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_L),
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_B),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_MODIFY_OP2_L),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B),
)
private val BTST_MODES = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_L),
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP2_L),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP2_B),
)
private val conditionCodes =
listOf("cc", "ls", "cs", "lt", "eq", "mi", "f", "ne", "ge", "pl", "gt", "t", "hi", "vc", "le", "vs")
private val conditionCodesBcc = conditionCodes.filterNot { it == "f" || it == "t" }
private val isaData = listOf(
// Data Movement Instructions
IsaData("move", "Move"),
IsaData("movea", "Move Address", altMnemonics = listOf("move"), opSize = "L"),
IsaData("movem", "Move Multiple Registers", opSize = "Wl"),
IsaData("movep", "Move Peripheral", opSize = ""),
IsaData("moveq", "Move Quick", opSize = "L"),
IsaData(
"move", "Move",
modes = listOf(AllowedAdrMode(ALL_68000_MODES, ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_READ_OP1_OPSIZE or RWM_SET_OP2_OPSIZE))
),
IsaData(
"movea", "Move Address", altMnemonics = listOf("move"),
modes = listOf(AllowedAdrMode(ALL_68000_MODES, AREG_ONLY, OP_SIZE_WL, modInfo = RWM_READ_OP1_OPSIZE or RWM_SET_OP2_L))
),
IsaData(
"movem", "Move Multiple Registers",
modes = listOf(
AllowedAdrMode(
setOf(AddressMode.REGISTER_LIST, AddressMode.ADDRESS_REGISTER_DIRECT, AddressMode.DATA_REGISTER_DIRECT),
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS
),
OP_SIZE_WL,
modInfo = RWM_READ_OP1_OPSIZE or RWM_SET_OP2_OPSIZE
),
AllowedAdrMode(
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
),
setOf(AddressMode.REGISTER_LIST, AddressMode.ADDRESS_REGISTER_DIRECT, AddressMode.DATA_REGISTER_DIRECT),
OP_SIZE_WL,
modInfo = RWM_READ_OP1_OPSIZE or RWM_SET_OP2_OPSIZE
),
// according to Yann, specifying the registers as bitmask is also valid
AllowedAdrMode(
setOf(AddressMode.IMMEDIATE_DATA),
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS
),
OP_SIZE_WL,
modInfo = RWM_SET_OP2_OPSIZE // Can't map immediate data to registers
),
AllowedAdrMode(
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS
),
setOf(AddressMode.IMMEDIATE_DATA),
OP_SIZE_WL,
modInfo = RWM_READ_OP1_OPSIZE // Can't map immediate data to registers
),
)
),
IsaData(
"movep", "Move Peripheral",
modes = listOf(
AllowedAdrMode(
DREG_ONLY,
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT, AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT),
OP_SIZE_WL,
modInfo = RWM_READ_OP1_OPSIZE
),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT, AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT),
DREG_ONLY,
OP_SIZE_WL,
modInfo = RWM_SET_OP2_OPSIZE
)
)
),
IsaData("exg", "Exchange Registers", opSize = "L"),
IsaData("lea", "Load Effective Address", opSize = ""),
IsaData("pea", "Push Effective Address", opSize = ""),
IsaData("link", "Link and Allocate", opSize = ""),
IsaData("unlk", "Unlink", opSize = ""),
IsaData(
"moveq", "Move Quick",
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_SET_OP2_L))
),
IsaData(
"exg", "Exchange Registers",
modes = listOf(
AllowedAdrMode(
setOf(AddressMode.DATA_REGISTER_DIRECT, AddressMode.ADDRESS_REGISTER_DIRECT),
setOf(AddressMode.DATA_REGISTER_DIRECT, AddressMode.ADDRESS_REGISTER_DIRECT),
OP_SIZE_L,
modInfo = RWM_SET_OP1_L or RWM_SET_OP2_L
)
)
),
IsaData(
"lea", "Load Effective Address",
modes = listOf(
AllowedAdrMode(
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
),
AREG_ONLY,
OP_SIZE_L,
modInfo = RWM_SET_OP2_L
)
)
),
IsaData(
"pea", "Push Effective Address",
modes = listOf(
AllowedAdrMode(
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX,
),
null,
OP_SIZE_L,
modInfo = RWM_MODIFY_STACK
)
)
),
IsaData(
"link", "Link and Allocate",
modes = listOf(AllowedAdrMode(AREG_ONLY, setOf(AddressMode.IMMEDIATE_DATA), OP_SIZE_W, modInfo = RWM_SET_OP1_L or RWM_MODIFY_STACK))
),
IsaData(
"unlk", "Unlink",
modes = listOf(AllowedAdrMode(AREG_ONLY, null, OP_UNSIZED, modInfo = RWM_SET_OP1_L or RWM_MODIFY_STACK))
),
// Integer Arithmetic Instructions
IsaData("add", "Add"),
IsaData("adda", "Add Address", altMnemonics = listOf("add"), opSize = "Wl"),
IsaData("addi", "Add Immediate", altMnemonics = listOf("add")),
IsaData("addq", "Add Quick"),
IsaData("addx", "Add with Extend"),
IsaData("add", "Add", modes = ADD_SUB_MODES),
IsaData(
"adda", "Add Address", altMnemonics = listOf("add"),
modes = listOf(
AllowedAdrMode(ALL_68000_MODES, AREG_ONLY, OP_SIZE_WL, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_L),
)
),
IsaData(
"addi", "Add Immediate", altMnemonics = listOf("add"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE))
),
IsaData(
"addq", "Add Quick", modes = listOf(
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), AREG_ONLY, size = OP_SIZE_WL, modInfo = RWM_MODIFY_OP2_L)
)
),
IsaData(
"addx", "Add with Extend",
modes = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE
)
)
),
IsaData("sub", "Subtract"),
IsaData("suba", "Subtract Address", altMnemonics = listOf("sub")),
IsaData("subi", "Subtract Immediate", altMnemonics = listOf("sub")),
IsaData("subq", "Subtract Quick"),
IsaData("subx", "Subtract with Extend"),
IsaData("sub", "Subtract", modes = ADD_SUB_MODES),
IsaData(
"suba", "Subtract Address", altMnemonics = listOf("sub"),
modes = listOf(AllowedAdrMode(ALL_68000_MODES, AREG_ONLY, OP_SIZE_WL, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_L))
),
IsaData(
"subi", "Subtract Immediate", altMnemonics = listOf("sub"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE))
),
IsaData(
"subq", "Subtract Quick", modes = listOf(
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), AREG_ONLY, size = OP_SIZE_WL, modInfo = RWM_MODIFY_OP2_L)
)
),
IsaData(
"subx", "Subtract with Extend",
modes = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE
)
)
),
IsaData("neg", "Negate"),
IsaData("negx", "Negate with Extend"),
IsaData("neg", "Negate", modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, modInfo = RWM_MODIFY_OP1_OPSIZE))),
IsaData("negx", "Negate with Extend", modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, modInfo = RWM_MODIFY_OP1_OPSIZE))),
IsaData("clr", "Clear"),
IsaData("clr", "Clear", modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, modInfo = RWM_SET_OP1_OPSIZE))),
IsaData("cmp", "Compare"),
IsaData("cmpa", "Compare Address", altMnemonics = listOf("cmp"), opSize = "Wl"),
IsaData("cmpi", "Compare Immediate", altMnemonics = listOf("cmp")),
IsaData("cmpm", "Compare Memory to Memory", altMnemonics = listOf("cmp")),
IsaData(
"cmp", "Compare", modes = listOf(
AllowedAdrMode(ALL_EXCEPT_AREG, setOf(AddressMode.DATA_REGISTER_DIRECT), modInfo = RWM_READ_OP1_OPSIZE or RWM_READ_OP2_OPSIZE),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_DIRECT),
setOf(AddressMode.DATA_REGISTER_DIRECT),
OP_SIZE_WL,
modInfo = RWM_READ_OP1_OPSIZE or RWM_READ_OP2_OPSIZE
),
)
),
IsaData(
"cmpa", "Compare Address", altMnemonics = listOf("cmp"),
modes = listOf(AllowedAdrMode(ALL_68000_MODES, AREG_ONLY, OP_SIZE_WL, modInfo = RWM_READ_OP1_OPSIZE or RWM_READ_OP2_L))
),
IsaData(
"cmpi", "Compare Immediate", altMnemonics = listOf("cmp"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_IMMEDIATE, modInfo = RWM_READ_OP2_OPSIZE))
),
IsaData(
"cmpm", "Compare Memory to Memory", altMnemonics = listOf("cmp"),
modes = listOf(
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC),
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC),
modInfo = RWM_READ_OP1_OPSIZE or RWM_READ_OP2_OPSIZE
)
)
),
IsaData("muls", "Signed Multiply", opSize = "W"),
IsaData("mulu", "Unsigned Multiply", opSize = "W"),
IsaData("divs", "Signed Divide", opSize = "W"),
IsaData("divu", "Unsigned Divide", opSize = "W"),
IsaData(
"muls", "Signed Multiply",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_W or RWM_MODIFY_OP2_L))
),
IsaData(
"mulu", "Unsigned Multiply",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_W or RWM_MODIFY_OP2_L))
),
IsaData(
"divs", "Signed Divide",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_L or RWM_MODIFY_OP2_L))
),
IsaData(
"divu", "Unsigned Divide",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_L or RWM_MODIFY_OP2_L))
),
IsaData("ext", "Sign Extend", opSize = "Wl"),
IsaData("ext", "Sign Extend", modes = listOf(AllowedAdrMode(DREG_ONLY, null, OP_SIZE_WL, modInfo = RWM_MODIFY_OP1_OPSIZE))),
// Logical Instructions
IsaData("and", "Logical AND"),
IsaData("andi", "Logical AND Immediate", altMnemonics = listOf("and")),
IsaData("eor", "Logical Exclusive-OR"),
IsaData("eori", "Logical Exclusive-OR Immediate", altMnemonics = listOf("eor")),
IsaData("not", "Logical Complement"),
IsaData("or", "Logical Inclusive-OR"),
IsaData("ori", "Logical Inclusive-OR Immediate", altMnemonics = listOf("or")),
IsaData(
"and", "Logical AND",
modes = listOf(
AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE)
)
),
IsaData(
"andi", "Logical AND Immediate", altMnemonics = listOf("and"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE))
),
IsaData(
"eor", "Logical Exclusive-OR",
modes = listOf(AllowedAdrMode(DREG_ONLY, ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE))
),
IsaData(
"eori", "Logical Exclusive-OR Immediate", altMnemonics = listOf("eor"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE))
),
IsaData(
"or", "Logical Inclusive-OR",
modes = listOf(
AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE)
)
),
IsaData(
"ori", "Logical Inclusive-OR Immediate", altMnemonics = listOf("or"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_MODIFY_OP2_OPSIZE))
),
IsaData(
"not", "Logical Complement",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, modInfo = RWM_MODIFY_OP1_OPSIZE))
),
// Shift and Rotate Instructions
IsaData("asl", "Arithmetic Shift Left"),
IsaData("asr", "Arithmetic Shift Right"),
IsaData("lsl", "Logical Shift Left"),
IsaData("lsr", "Logical Shift Right"),
IsaData("rol", "Rotate Left"),
IsaData("ror", "Rotate Right"),
IsaData("roxl", "Rotate with Extend Left"),
IsaData("roxr", "Rotate with Extend Right"),
IsaData("swap", "Swap Register Words", opSize = ""),
IsaData("asl", "Arithmetic Shift Left", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("asr", "Arithmetic Shift Right", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("lsl", "Logical Shift Left", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("lsr", "Logical Shift Right", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("rol", "Rotate Left", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("ror", "Rotate Right", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("roxl", "Rotate with Extend Left", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("roxr", "Rotate with Extend Right", modes = ASD_LSD_ROD_ROXD_MODES),
IsaData("swap", "Swap Register Words", modes = listOf(AllowedAdrMode(DREG_ONLY, null, OP_SIZE_W, modInfo = RWM_MODIFY_OP1_L))),
// Bit Manipulation Instructions
IsaData("bchg", "Test Bit and Change", opSize = "Bl"),
IsaData("bclr", "Test Bit and Clear", opSize = "Bl"),
IsaData("bset", "Test Bit and Set", opSize = "Bl"),
IsaData("btst", "Test Bit", opSize = "Bl"),
IsaData("bchg", "Test Bit and Change", modes = BCHG_BCLR_BSET_MODES),
IsaData("bclr", "Test Bit and Clear", modes = BCHG_BCLR_BSET_MODES),
IsaData("bset", "Test Bit and Set", modes = BCHG_BCLR_BSET_MODES),
IsaData("btst", "Test Bit", modes = BTST_MODES),
// Binary-Coded Decimal Instructions
IsaData("abcd", "Add Decimal with Extend", opSize = ""),
IsaData("sbcd", "Subtract Decimal with Extend", opSize = ""),
IsaData("nbcd", "Negate Decimal with Extend", opSize = ""),
IsaData(
"abcd", "Add Decimal with Extend",
modes = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_B, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
OP_SIZE_B,
modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE
)
)
),
IsaData(
"sbcd", "Subtract Decimal with Extend",
modes = listOf(
AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_B, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
AllowedAdrMode(
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
setOf(AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC),
OP_SIZE_B,
modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE
)
)
),
IsaData(
"nbcd", "Negate Decimal with Extend",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, OP_SIZE_B, modInfo = RWM_MODIFY_OP1_OPSIZE))
),
// Program Control Instructions
IsaData("bCC", "Branch Conditionally", conditionCodes = conditionCodesBcc, opSize = "bsW"),
IsaData("bra", "Branch", opSize = "bsW"),
IsaData("bsr", "Branch to Subroutine", opSize = "bsW"),
IsaData(
"bCC", "Branch Conditionally", conditionCodes = conditionCodesBcc,
modes = listOf(AllowedAdrMode(setOf(AddressMode.ABSOLUTE_ADDRESS), null, OP_SIZE_SBW))
),
IsaData("bra", "Branch", modes = listOf(AllowedAdrMode(setOf(AddressMode.ABSOLUTE_ADDRESS), null, OP_SIZE_SBW))),
IsaData(
"bsr",
"Branch to Subroutine",
modes = listOf(AllowedAdrMode(setOf(AddressMode.ABSOLUTE_ADDRESS), null, OP_SIZE_SBW, modInfo = RWM_MODIFY_STACK))
),
IsaData(
"dbCC",
"Test Condition, Decrement, and Branch",
altMnemonics = listOf("dbra"),
conditionCodes = conditionCodes, opSize = "W"
conditionCodes = conditionCodes,
modes = listOf(AllowedAdrMode(DREG_ONLY, setOf(AddressMode.ABSOLUTE_ADDRESS), OP_SIZE_W, modInfo = RWM_MODIFY_OP1_W))
),
IsaData(
"sCC", "Set Conditionally", conditionCodes = conditionCodes,
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, OP_SIZE_B, modInfo = RWM_SET_OP2_B))
),
IsaData("sCC", "Set Conditionally", conditionCodes = conditionCodes, opSize = ""),
IsaData("jmp", "Jump", opSize = ""),
IsaData("jsr", "Jump to Subroutine", opSize = ""),
IsaData("nop", "No Operation", opSize = "", hasOps = false),
IsaData(
"jmp", "Jump",
modes = listOf(
AllowedAdrMode(
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
), null, OP_UNSIZED
)
)
),
IsaData(
"jsr", "Jump to Subroutine",
modes = listOf(
AllowedAdrMode(
setOf(
AddressMode.ADDRESS_REGISTER_INDIRECT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX,
AddressMode.ABSOLUTE_ADDRESS,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT,
AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
), null, OP_UNSIZED, modInfo = RWM_MODIFY_STACK
)
)
),
IsaData("nop", "No Operation", hasOps = false, modes = NO_OPS_UNSIZED),
IsaData("rtr", "Return and Restore", hasOps = false),
IsaData("rts", "Return from Subroutine", hasOps = false),
IsaData("rtr", "Return and Restore", hasOps = false, modes = listOf(AllowedAdrMode(size = OP_UNSIZED, modInfo = RWM_MODIFY_STACK))),
IsaData("rts", "Return from Subroutine", hasOps = false, modes = listOf(AllowedAdrMode(size = OP_UNSIZED, modInfo = RWM_MODIFY_STACK))),
IsaData("tst", "Test Operand"),
IsaData("tst", "Test Operand", modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, modInfo = RWM_READ_OP1_OPSIZE))),
// System Control Instructions
IsaData("andi", "AND Immediate to Status Register", id = "andi to SR", altMnemonics = listOf("and"), isPrivileged = true),
IsaData("eori", "Exclusive-OR Immediate to Status Register", id = "eori to SR", altMnemonics = listOf("eor"), isPrivileged = true),
IsaData("ori", "Inclusive-OR Immediate to Status Register", id = "ori to SR", altMnemonics = listOf("or"), isPrivileged = true),
IsaData("move", "Move from Status Register", id = "move from SR"),
IsaData("move", "Move to Status Register", id = "move to SR", isPrivileged = true),
IsaData("move", "Move User Stack Pointer", id = "move USP", isPrivileged = true),
IsaData(
"andi", "AND Immediate to Status Register", id = "andi to SR", altMnemonics = listOf("and"), isPrivileged = true,
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "sr"))
),
IsaData(
"eori", "Exclusive-OR Immediate to Status Register", id = "eori to SR", altMnemonics = listOf("eor"), isPrivileged = true,
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "sr"))
),
IsaData(
"ori", "Inclusive-OR Immediate to Status Register", id = "ori to SR", altMnemonics = listOf("or"), isPrivileged = true,
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "sr"))
),
IsaData(
"move", "Move from Status Register", id = "move from SR",
modes = listOf(
AllowedAdrMode(
setOf(AddressMode.SPECIAL_REGISTER_DIRECT),
ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL,
OP_SIZE_W,
"sr",
modInfo = RWM_SET_OP2_W
)
)
),
IsaData(
"move", "Move to Status Register", id = "move to SR", isPrivileged = true,
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "sr"))
),
IsaData(
"move", "Move User Stack Pointer", id = "move USP", isPrivileged = true,
modes = listOf(
AllowedAdrMode(setOf(AddressMode.SPECIAL_REGISTER_DIRECT), AREG_ONLY, OP_SIZE_L, "usp", modInfo = RWM_SET_OP2_L),
AllowedAdrMode(AREG_ONLY, setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_L, "usp", modInfo = RWM_READ_OP1_L),
)
),
IsaData("reset", "Reset External Devices", opSize = "", isPrivileged = true, hasOps = false),
IsaData("rte", "Return from Exception", isPrivileged = true, hasOps = false),
IsaData("stop", "Stop", opSize = "", isPrivileged = true),
IsaData("reset", "Reset External Devices", isPrivileged = true, hasOps = false, modes = NO_OPS_UNSIZED),
IsaData(
"rte", "Return from Exception", isPrivileged = true, hasOps = false,
modes = listOf(AllowedAdrMode(size = OP_UNSIZED, modInfo = RWM_MODIFY_STACK))
),
IsaData(
"stop", "Stop", isPrivileged = true,
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), null, OP_UNSIZED))
),
IsaData("chk", "Check Register Against Bound"),
IsaData("illegal", "Take Illegal Instruction Trap", opSize = "", hasOps = false),
IsaData("trap", "Trap", opSize = ""),
IsaData("trapv", "Trap on Overflow", opSize = ""),
IsaData("andi", "AND Immediate to Condition Code Register", id = "andi to CCR", altMnemonics = listOf("and")),
IsaData("eori", "Exclusive-OR Immediate to Condition Code Register", id = "eori to CCR", altMnemonics = listOf("eor")),
IsaData("ori", "Inclusive-OR Immediate to Condition Code Register", id = "ori to CCR", altMnemonics = listOf("or")),
IsaData("move", "Move to Condition Code Register", id = "move to CCR"),
IsaData(
"chk", "Check Register Against Bound",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_W or RWM_READ_OP2_W))
),
IsaData("illegal", "Take Illegal Instruction Trap", hasOps = false, modes = NO_OPS_UNSIZED),
IsaData("trap", "Trap", modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), null, OP_UNSIZED))),
IsaData("trapv", "Trap on Overflow", hasOps = false, modes = NO_OPS_UNSIZED),
IsaData(
"andi", "AND Immediate to Condition Code Register", id = "andi to CCR", altMnemonics = listOf("and"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "ccr"))
),
IsaData(
"eori", "Exclusive-OR Immediate to Condition Code Register", id = "eori to CCR", altMnemonics = listOf("eor"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "ccr"))
),
IsaData(
"ori", "Inclusive-OR Immediate to Condition Code Register", id = "ori to CCR", altMnemonics = listOf("or"),
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "ccr"))
),
IsaData(
"move", "Move to Condition Code Register", id = "move to CCR",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, setOf(AddressMode.SPECIAL_REGISTER_DIRECT), OP_SIZE_W, "ccr"))
),
// Multiprocessor Instructions
IsaData("tas", "Test Operand and Set", opSize = "B"),
IsaData(
"tas", "Test Operand and Set",
modes = listOf(AllowedAdrMode(ALL_EXCEPT_IMMEDIATE_AND_PC_REL, null, OP_SIZE_B, modInfo = RWM_MODIFY_OP1_B))
)
)
val mnemonics =
isaData.asSequence()
@@ -161,4 +734,54 @@ object M68kIsa {
})
}
.toSet()
fun findMatchingInstructions(mnemonic: String): List<IsaData> {
val lowerMnemonic = mnemonic.lowercase()
return isaData
.filter {
if (it.conditionCodes.isEmpty()) {
(it.mnemonic == lowerMnemonic) || it.altMnemonics.any { altMnemonic -> altMnemonic == lowerMnemonic }
} else {
it.altMnemonics.any { altMnemonic -> altMnemonic == lowerMnemonic } ||
it.conditionCodes.any { cc ->
it.mnemonic.replace("CC", cc) == lowerMnemonic
}
}
}
}
fun findMatchingOpMode(candidates: List<IsaData>, op1: AddressMode?, op2: AddressMode?, opSize: Int?, specialReg: String?): List<IsaData> {
return candidates.filter {
it.modes.any { am ->
isAddressModeMatching(am, op1, op2, specialReg)
&& ((opSize == null) || ((opSize and am.size) == opSize))
}
}
}
fun findMatchingAddressMode(modes: List<AllowedAdrMode>, op1: AddressMode?, op2: AddressMode?, opSize: Int?, specialReg: String?): List<AllowedAdrMode> {
return modes.filter { am ->
isAddressModeMatching(am, op1, op2, specialReg)
&& ((opSize == null) || ((opSize and am.size) == opSize))
}
}
fun findMatchingOpModeIgnoringSize(candidates: List<IsaData>, op1: AddressMode?, op2: AddressMode?, specialReg: String?): List<IsaData> {
return candidates.filter {
it.modes.any { am -> isAddressModeMatching(am, op1, op2, specialReg) }
}
}
fun findSupportedOpSizes(candidates: List<IsaData>, op1: AddressMode?, op2: AddressMode?, specialReg: String?): Int {
return candidates.fold(OP_UNSIZED) { acc, isaData ->
acc or isaData.modes.fold(OP_UNSIZED) { am_acc, am ->
if (isAddressModeMatching(am, op1, op2, specialReg)) am_acc or am.size else am_acc
}
}
}
private fun isAddressModeMatching(am: AllowedAdrMode, op1: AddressMode?, op2: AddressMode?, specialReg: String?) =
((((op1 == null) && (am.op1 == null)) || am.op1?.contains(op1) ?: false)
&& (((op2 == null) && (am.op2 == null)) || am.op2?.contains(op2) ?: false)
&& ((specialReg == null) || (specialReg == am.specialReg)))
}
@@ -4,13 +4,20 @@ import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
class M68kMnemonicCompletionContributor : CompletionContributor() {
companion object {
val MNEMONICS = M68kIsa.mnemonics
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.MNEMONIC), 10.0) }
}
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOKATION), object : CompletionProvider<CompletionParameters>() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOCATION), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(M68kIsa.mnemonics.map(LookupElementBuilder::create))
resultSet.addAllElements(MNEMONICS)
}
})
}
@@ -0,0 +1,102 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.lang.documentation.AbstractDocumentationProvider
import com.intellij.lang.documentation.DocumentationMarkup
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.text.HtmlBuilder
import com.intellij.openapi.util.text.HtmlChunk
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import de.platon42.intellij.plugins.m68k.asm.AddressMode
import de.platon42.intellij.plugins.m68k.asm.IsaData
import de.platon42.intellij.plugins.m68k.asm.M68kIsa
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataForInstruction
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findOpSizeDescriptions
class M68kInstructionDocumentationProvider : AbstractDocumentationProvider() {
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
if (element is M68kAsmInstruction) {
val builder = HtmlBuilder()
val isaData = findExactIsaDataForInstruction(element)
if (isaData == null) {
M68kIsa.findMatchingInstructions(element.asmOp.mnemonic).forEach { buildDocForIsaData(it, builder) }
} else {
buildDocForIsaData(isaData, builder)
}
return builder.toString()
}
return null
}
private fun buildDocForIsaData(isaData: IsaData, builder: HtmlBuilder) {
val defBuilder = createDefinition(isaData)
builder.append(defBuilder.wrapWith(DocumentationMarkup.DEFINITION_ELEMENT))
val mnemonicInfoRows = HtmlBuilder()
val headerCells = listOf(
HtmlChunk.text("Mnemonic").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
HtmlChunk.text("Op1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
HtmlChunk.text("Op2").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
)
mnemonicInfoRows.append(HtmlChunk.tag("tr").children(headerCells))
isaData.modes.forEach { allowedAdrMode ->
val mnemonics = findOpSizeDescriptions(allowedAdrMode.size)
.map { HtmlChunk.text(isaData.mnemonic + it).wrapWith(HtmlChunk.div()) }
mnemonicInfoRows.append(
HtmlChunk.tag("tr").children(
DocumentationMarkup.SECTION_CONTENT_CELL.children(mnemonics),
DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op1)),
DocumentationMarkup.SECTION_CONTENT_CELL.child(collectAddressModes(allowedAdrMode.op2))
)
)
}
val contentBuilder = HtmlBuilder()
contentBuilder.append(mnemonicInfoRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE))
builder.append(contentBuilder.wrapWith(DocumentationMarkup.CONTENT_ELEMENT))
}
override fun generateHoverDoc(element: PsiElement, originalElement: PsiElement?): String? {
if (element is M68kAsmInstruction) {
val isaData = findExactIsaDataForInstruction(element) ?: return null
val defBuilder = createDefinition(isaData)
val builder = HtmlBuilder()
builder.append(defBuilder.wrapWith(DocumentationMarkup.DEFINITION_ELEMENT))
return builder.toString()
}
return null
}
private fun createDefinition(isaData: IsaData): HtmlBuilder {
val defBuilder = HtmlBuilder()
defBuilder.append(HtmlChunk.text(isaData.description).bold().wrapWith("pre"))
if (isaData.isPrivileged) {
defBuilder.append(HtmlChunk.font("red").addText("(privileged)").wrapWith(HtmlChunk.p()))
}
return defBuilder
}
private fun collectAddressModes(addressModes: Set<AddressMode>?): HtmlChunk {
if (addressModes == null) return HtmlChunk.text("")
val modes = HtmlBuilder()
addressModes.sortedBy(AddressMode::ordinal)
.forEach { modes.append(HtmlChunk.text(it.syntax).wrapWith(HtmlChunk.div())) }
return modes.toFragment()
}
override fun getCustomDocumentationElement(editor: Editor, file: PsiFile, contextElement: PsiElement?, targetOffset: Int): PsiElement? {
if (contextElement == null) return null
if (contextElement is M68kAsmInstruction) return contextElement
val parent = contextElement.parent ?: return null
if (parent is M68kAsmInstruction) return parent
if (parent is M68kAsmOp) return parent.parent
if (parent is M68kOperandSize) return parent.parent.parent
return null
}
}
@@ -0,0 +1,244 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.lang.documentation.AbstractDocumentationProvider
import com.intellij.lang.documentation.DocumentationMarkup
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.text.HtmlBuilder
import com.intellij.openapi.util.text.HtmlChunk
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.ui.ColorUtil
import com.intellij.ui.JBColor
import de.platon42.intellij.plugins.m68k.asm.*
import de.platon42.intellij.plugins.m68k.asm.Register.Companion.getRegFromName
import de.platon42.intellij.plugins.m68k.psi.*
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getOtherReadWriteModifyRegisters
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getReadWriteModifyRegisters
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.getOpSizeOrDefault
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.modifyRwmWithOpsize
class M68kRegisterFlowDocumentationProvider : AbstractDocumentationProvider() {
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
if (element is M68kDataRegister || element is M68kAddressRegister) {
return createDoc(element as M68kRegister, 100) // TODO make this configurable
}
return null
}
override fun generateHoverDoc(element: PsiElement, originalElement: PsiElement?): String? {
if (element is M68kDataRegister || element is M68kAddressRegister) {
return createDoc(element as M68kRegister, 4) // TODO make this configurable
}
return null
}
private fun createDoc(element: M68kRegister, linesLimit: Int): String? {
val register = getRegFromName(element.text)
val addressingMode = PsiTreeUtil.getParentOfType(element, M68kAddressingMode::class.java) ?: return null
val asmInstruction = PsiTreeUtil.getParentOfType(addressingMode, M68kAsmInstruction::class.java) ?: return null
val (isaData, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return "unknown instruction"
val cursorInstRwmRegs = evaluateRegisterUse(asmInstruction, adrMode, register)
val opSize = getOpSizeOrDefault(asmInstruction.asmOp.opSize, adrMode)
val rn = register.regname
val thisInfo = cursorInstRwmRegs
.joinToString(separator = ", ", prefix = "${isaData.mnemonic} instruction ") { rwmToDisplayText(it, rn) }
val totalRwm = cursorInstRwmRegs.reduce(Int::or)
val firstOp = asmInstruction.addressingModeList[0] == addressingMode
val cursorRwm = modifyRwmWithOpsize((adrMode.modInfo ushr if (firstOp) RWM_OP1_SHIFT else RWM_OP2_SHIFT) and RWM_OP_MASK, opSize)
val backtrace: MutableList<HtmlChunk> = ArrayList()
val missingBits = if (cursorRwm and RWM_SET_L != 0) {
if (totalRwm and RWM_SET_L == RWM_SET_L) {
backtrace.add(
HtmlChunk.tag("tr")
.children(
DocumentationMarkup.SECTION_CONTENT_CELL.attr("colspan", "3")
.child(HtmlChunk.text("Register result is fully defined by this instruction."))
)
)
0
} else {
(RWM_SET_L and RWM_SIZE_MASK) and totalRwm.inv()
}
} else {
(RWM_SET_L and RWM_SIZE_MASK) and ((cursorRwm and RWM_MODIFY_L) ushr 8)
}
val initialStatement: M68kStatement = asmInstruction.parent as M68kStatement
val localLabelName = PsiTreeUtil.findChildOfType(initialStatement, M68kLocalLabel::class.java)?.name ?: "-->"
backtrace.add(
HtmlChunk.tag("tr")
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(localLabelName)))
.children(highlightRegister(asmInstruction, register).bold().wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(" ; <--")))
)
backtrace.addAll(analyseFlow(register, missingBits, true, initialStatement, linesLimit) {
PsiTreeUtil.getPrevSiblingOfType(
it,
M68kStatement::class.java
)
})
backtrace.reverse()
val traceBits = (cursorRwm or (cursorRwm ushr 8)) and RWM_SIZE_MASK
backtrace.addAll(analyseFlow(register, traceBits, false, initialStatement, linesLimit) {
PsiTreeUtil.getNextSiblingOfType(
it,
M68kStatement::class.java
)
})
val statementRows = HtmlBuilder()
backtrace.forEach(statementRows::append)
val builder = HtmlBuilder()
builder.append(HtmlChunk.text(thisInfo).wrapWith(DocumentationMarkup.DEFINITION_ELEMENT))
builder.append(statementRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE.style("padding-left: 8pt; padding-right: 8pt")))
return builder.toString()
}
private fun analyseFlow(
register: Register,
rwmBits: Int,
globalLabelBreaksOnInitialStatement: Boolean,
startingStatement: M68kStatement,
linesLimit: Int,
direction: (statement: M68kStatement) -> M68kStatement?
): MutableList<HtmlChunk> {
var missingBits = rwmBits
var currStatement = startingStatement
val statementLines: MutableList<HtmlChunk> = ArrayList()
val rn = register.regname
var addAbrevDots = false
var lines = 0
while (missingBits > 0) {
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
if ((globalLabel != null) && (globalLabelBreaksOnInitialStatement || (currStatement !== startingStatement))) {
statementLines.add(
HtmlChunk.tag("tr")
.children(DocumentationMarkup.SECTION_CONTENT_CELL.attr("colspan", "3").child(HtmlChunk.text(globalLabel.name!!).bold()))
)
break
}
currStatement = direction.invoke(currStatement) ?: break
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
if (checkIfInstructionUsesRegister(currAsmInstruction, register)) {
if (addAbrevDots) {
++lines
statementLines.add(createAbbreviationDots())
}
if (++lines > linesLimit) {
if (!addAbrevDots) {
statementLines.add(createAbbreviationDots())
}
break
}
addAbrevDots = false
val (_, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: continue
val localLabelName = PsiTreeUtil.findChildOfType(currStatement, M68kLocalLabel::class.java)?.name ?: "        "
val currRwms = evaluateRegisterUse(currAsmInstruction, currAdrMode, register)
val currTotalRwm = currRwms.reduce(Int::or)
val lineInfo = currRwms
.map {
val text = HtmlChunk.text(rwmToDisplayText(it, rn))
if ((missingBits and it) > 0) text.wrapWith(HtmlChunk.font("#" + ColorUtil.toHex(JBColor.GREEN))) else text
}
if ((currTotalRwm and RWM_SET_L) > 0) {
missingBits = missingBits and currTotalRwm.inv()
}
val lineBuilder = HtmlBuilder()
lineBuilder.append(" ; ")
lineBuilder.appendWithSeparators(HtmlChunk.text(", "), lineInfo)
.wrapWith(HtmlChunk.div())
statementLines.add(
HtmlChunk.tag("tr")
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.text(localLabelName)))
.children(highlightRegister(currAsmInstruction, register).wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
.children(lineBuilder.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL))
)
} else {
addAbrevDots = true
}
}
return statementLines
}
private fun highlightRegister(currAsmInstruction: M68kAsmInstruction, register: Register): HtmlChunk {
val builder = HtmlBuilder()
val plainText = currAsmInstruction.text
var startPos = 0
val rn = if (register == Register.A7) listOf(register.regname, "sp") else listOf(register.regname)
do {
val indexPos = plainText.indexOfAny(rn, startPos, ignoreCase = true)
if (indexPos >= 0) {
builder.append(HtmlChunk.text(plainText.substring(startPos until indexPos)))
startPos = indexPos + register.regname.length
builder.append(HtmlChunk.text(plainText.substring(indexPos until startPos)).wrapWith(HtmlChunk.font("#" + ColorUtil.toHex(JBColor.ORANGE))))
} else {
builder.append(HtmlChunk.text(plainText.substring(startPos)))
}
} while (indexPos >= 0)
return builder.toFragment().code()
}
private fun rwmToDisplayText(rwm: Int, rn: String) =
when (rwm) {
RWM_READ_B -> "reads $rn.b"
RWM_READ_W -> "reads $rn.w"
RWM_READ_L -> "reads $rn.l"
RWM_MODIFY_B -> "modifies $rn.b"
RWM_MODIFY_W -> "modifies $rn.w"
RWM_MODIFY_L -> "modifies $rn.l"
RWM_SET_B -> "sets $rn.b"
RWM_SET_W -> "sets $rn.w"
RWM_SET_L -> "sets $rn.l"
else -> "uhm?"
}
private fun createAbbreviationDots() = HtmlChunk.tag("tr")
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.nbsp()))
.children(
DocumentationMarkup.SECTION_CONTENT_CELL.child(
HtmlChunk.text("[...]").wrapWith(HtmlChunk.div().attr("class", "grayed"))
)
)
.children(DocumentationMarkup.SECTION_CONTENT_CELL.child(HtmlChunk.nbsp()))
private fun evaluateRegisterUse(
asmInstruction: M68kAsmInstruction,
adrMode: AllowedAdrMode,
register: Register
): List<Int> {
val opSize = getOpSizeOrDefault(asmInstruction.asmOp.opSize, adrMode)
val rwm1 = modifyRwmWithOpsize((adrMode.modInfo ushr RWM_OP1_SHIFT) and RWM_OP_MASK, opSize)
val rwm2 = if (asmInstruction.addressingModeList.size > 1) modifyRwmWithOpsize((adrMode.modInfo ushr RWM_OP2_SHIFT) and RWM_OP_MASK, opSize) else 0
return getReadWriteModifyRegisters(asmInstruction.addressingModeList[0], rwm1).asSequence()
.plus(getReadWriteModifyRegisters(asmInstruction.addressingModeList.getOrNull(1), rwm2))
.plus(getOtherReadWriteModifyRegisters(adrMode.modInfo))
.filter { it.first == register }
.map { it.second }
.toList()
}
private fun checkIfInstructionUsesRegister(instruction: M68kAsmInstruction, register: Register): Boolean {
if (instruction.addressingModeList.isEmpty()) {
return false
}
return instruction.addressingModeList.any { aml -> getReadWriteModifyRegisters(aml, 0).any { it.first == register } }
}
override fun getCustomDocumentationElement(editor: Editor, file: PsiFile, contextElement: PsiElement?, targetOffset: Int): PsiElement? {
if (contextElement == null) return null
if (contextElement is M68kDataRegister || contextElement is M68kAddressRegister) return contextElement
val parent = contextElement.parent ?: return null
if (parent is M68kDataRegister || parent is M68kAddressRegister) return parent
return null
}
}
@@ -0,0 +1,24 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.lang.documentation.AbstractDocumentationProvider
import com.intellij.lang.documentation.DocumentationMarkup
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import de.platon42.intellij.plugins.m68k.psi.M68kAssignment
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
class M68kSymbolDefinitionDocumentationProvider : AbstractDocumentationProvider() {
override fun getQuickNavigateInfo(element: PsiElement, originalElement: PsiElement?): String? {
return generateDoc(element, originalElement)
}
override fun generateDoc(element: PsiElement, originalElement: PsiElement?): String? {
return if (element is M68kSymbolDefinition) {
// TODO find out how we can generate inner links for more symbol references inside the expression (DocumentationManagerUtil)
val value = (element.getParent() as M68kAssignment).expr.text
DocumentationMarkup.DEFINITION_START + StringUtil.escapeXmlEntities(element.name!!) + DocumentationMarkup.DEFINITION_END +
DocumentationMarkup.CONTENT_START + StringUtil.escapeXmlEntities(value) + DocumentationMarkup.CONTENT_END
} else null
}
}
@@ -0,0 +1,44 @@
package de.platon42.intellij.plugins.m68k.inspections
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalInspectionTool
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import de.platon42.intellij.plugins.m68k.psi.*
abstract class AbstractBaseM68kLocalInspectionTool : LocalInspectionTool() {
protected open fun checkStatement(statement: M68kStatement, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? = null
protected open fun checkAsmInstruction(asmInstruction: M68kAsmInstruction, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? =
null
protected open fun checkMacroCall(macroCall: M68kMacroCall, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? = null
protected open fun checkDirective(directive: M68kPreprocessorDirective, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? = null
protected open fun checkRegister(register: M68kRegister, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? = null
override fun getGroupDisplayName() = "M68k"
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
return object : M68kVisitor() {
override fun visitStatement(statement: M68kStatement) = addDescriptors(checkStatement(statement, holder.manager, isOnTheFly))
override fun visitAsmInstruction(asmInstruction: M68kAsmInstruction) =
addDescriptors(checkAsmInstruction(asmInstruction, holder.manager, isOnTheFly))
override fun visitMacroCall(macroCall: M68kMacroCall) = addDescriptors(checkMacroCall(macroCall, holder.manager, isOnTheFly))
override fun visitPreprocessorDirective(directive: M68kPreprocessorDirective) =
addDescriptors(checkDirective(directive, holder.manager, isOnTheFly))
override fun visitRegister(register: M68kRegister) = addDescriptors(checkRegister(register, holder.manager, isOnTheFly))
private fun addDescriptors(descriptors: Array<ProblemDescriptor>?) {
descriptors?.forEach(holder::registerProblem)
}
}
}
}
@@ -0,0 +1,169 @@
package de.platon42.intellij.plugins.m68k.inspections
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.codeInspection.ProblemHighlightType
import de.platon42.intellij.plugins.m68k.asm.*
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingInstructions
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingOpMode
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingOpModeIgnoringSize
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findSupportedOpSizes
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil.getAddressModeForType
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
import de.platon42.intellij.plugins.m68k.psi.M68kSpecialRegisterDirectAddressingMode
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil
class M68kSyntaxInspection : AbstractBaseM68kLocalInspectionTool() {
companion object {
private const val DISPLAY_NAME = "Assembly instruction validity"
private const val INSTRUCTION_NOT_FOUND_MSG = "Instruction '#ref' not supported on selected cpu"
private const val OPERANDS_UNEXPECTED_MSG_TEMPLATE = "No operands expected for '%s'"
private const val SECOND_OP_UNEXPECTED_MSG_TEMPLATE = "Second operand '#ref' unexpected for '%s'"
private const val UNSUPPORTED_ADDRESSING_MODE_MSG_TEMPLATE = "Unsupported addressing mode for '%s'"
private const val UNSUPPORTED_ADDRESSING_MODE_OP1_MSG_TEMPLATE = "Unsupported addressing mode '#ref' for first operand of '%s'"
private const val UNSUPPORTED_ADDRESSING_MODE_OP2_MSG_TEMPLATE = "Unsupported addressing mode '#ref' for second operand of '%s'"
private const val UNSUPPORTED_ADDRESSING_MODE_FLIP_MSG_TEMPLATE = "Unsupported addressing modes for operands in this order for '%s'"
private const val UNSUPPORTED_SIZE_UNSIZED_MSG_TEMPLATE = "Instruction '%s' is unsized"
private const val UNSUPPORTED_SIZE_MSG_TEMPLATE = "Operation size '#ref' unsupported for '%s"
private const val UNSUPPORTED_SIZE_HINT_MSG_TEMPLATE = "Operation size '#ref' unsupported (should be %s)"
}
override fun getDisplayName() = DISPLAY_NAME
override fun checkAsmInstruction(asmInstruction: M68kAsmInstruction, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? {
val asmOp = asmInstruction.asmOp
val mnemonicWithSize = asmOp.text
val isaData = findMatchingInstructions(asmOp.mnemonic)
if (isaData.isEmpty()) {
return arrayOf(
manager.createProblemDescriptor(
asmOp,
INSTRUCTION_NOT_FOUND_MSG,
null as LocalQuickFix?,
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
if (asmInstruction.addressingModeList.isNotEmpty() && isaData.none { it.hasOps }) {
return arrayOf(
manager.createProblemDescriptor(
asmInstruction.addressingModeList.first(),
asmInstruction.addressingModeList.last(),
OPERANDS_UNEXPECTED_MSG_TEMPLATE.format(mnemonicWithSize),
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
val amOp1 = asmInstruction.addressingModeList.getOrNull(0)
val amOp2 = asmInstruction.addressingModeList.getOrNull(1)
val op1 = getAddressModeForType(amOp1)
val op2 = getAddressModeForType(amOp2)
val specialReg1 = (amOp1 as? M68kSpecialRegisterDirectAddressingMode)?.specialRegister?.text
val specialReg2 = (amOp2 as? M68kSpecialRegisterDirectAddressingMode)?.specialRegister?.text
val specialReg = specialReg1 ?: specialReg2
val opSize = asmOp.opSize
val matchingModeIsaData = findMatchingOpMode(isaData, op1, op2, opSize, specialReg)
if (matchingModeIsaData.isEmpty()) {
val matchingModeIsaDataIgnoringSize = findMatchingOpModeIgnoringSize(isaData, op1, op2, specialReg)
if (matchingModeIsaDataIgnoringSize.isEmpty()) {
val matchingModeIsaDataSwapped = findMatchingOpModeIgnoringSize(isaData, op2, op1, specialReg)
val supportedModesOp1 = isaData.flatMap { it.modes.flatMap { am -> am.op1 ?: emptySet() } }.toSet()
val supportedModesOp2 = isaData.flatMap { it.modes.flatMap { am -> am.op2 ?: emptySet() } }.toSet()
if (matchingModeIsaDataSwapped.isNotEmpty()) {
return arrayOf(
manager.createProblemDescriptor(
asmInstruction,
UNSUPPORTED_ADDRESSING_MODE_FLIP_MSG_TEMPLATE.format(mnemonicWithSize),
null as LocalQuickFix?, // TODO add flipping quickfix
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
if ((op2 != null)) {
if (supportedModesOp2.isEmpty()) {
return arrayOf(
manager.createProblemDescriptor(
asmInstruction.addressingModeList[1],
SECOND_OP_UNEXPECTED_MSG_TEMPLATE.format(mnemonicWithSize),
null as LocalQuickFix?,
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
if (supportedModesOp1.contains(op1) && !supportedModesOp2.contains(op2)) {
return arrayOf(
manager.createProblemDescriptor(
asmInstruction.addressingModeList[1],
UNSUPPORTED_ADDRESSING_MODE_OP2_MSG_TEMPLATE.format(mnemonicWithSize),
null as LocalQuickFix?,
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
if (supportedModesOp2.contains(op2) && !supportedModesOp1.contains(op1)) {
return arrayOf(
manager.createProblemDescriptor(
asmInstruction.addressingModeList[0],
UNSUPPORTED_ADDRESSING_MODE_OP1_MSG_TEMPLATE.format(mnemonicWithSize),
null as LocalQuickFix?,
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
}
return arrayOf(
manager.createProblemDescriptor(
asmInstruction.addressingModeList.firstOrNull() ?: asmInstruction,
asmInstruction.addressingModeList.lastOrNull() ?: asmInstruction,
UNSUPPORTED_ADDRESSING_MODE_MSG_TEMPLATE.format(mnemonicWithSize),
ProblemHighlightType.ERROR,
isOnTheFly
)
)
}
val supportedOpSizes = findSupportedOpSizes(matchingModeIsaDataIgnoringSize, op1, op2, specialReg)
return arrayOf(
when (supportedOpSizes) {
OP_UNSIZED ->
manager.createProblemDescriptor(
asmOp.operandSize ?: asmOp,
UNSUPPORTED_SIZE_UNSIZED_MSG_TEMPLATE.format(asmOp.mnemonic),
null as LocalQuickFix?, // TODO remove size quickfix?
ProblemHighlightType.ERROR,
isOnTheFly
)
OP_SIZE_B, OP_SIZE_W, OP_SIZE_L, OP_SIZE_WL, OP_SIZE_SBW ->
manager.createProblemDescriptor(
asmOp.operandSize ?: asmOp,
UNSUPPORTED_SIZE_HINT_MSG_TEMPLATE.format(M68kIsaUtil.findOpSizeDescription(supportedOpSizes)),
null as LocalQuickFix?, // TODO change size to .b?
ProblemHighlightType.ERROR,
isOnTheFly
)
else ->
manager.createProblemDescriptor(
asmOp.operandSize ?: asmOp,
UNSUPPORTED_SIZE_MSG_TEMPLATE.format(asmOp.mnemonic),
null as LocalQuickFix?, // TODO remove size quickfix?
ProblemHighlightType.ERROR,
isOnTheFly
)
}
)
}
return emptyArray()
}
}
@@ -4,10 +4,12 @@ import com.intellij.psi.TokenType
import com.intellij.psi.tree.IElementType
import de.platon42.intellij.plugins.m68k.asm.AssemblerDirectives
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.mnemonics
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
object LexerUtil {
private val ASSIGNMENT_SEPARATORS = charArrayOf(' ', '\t', '=', ':')
private val TOKEN_SEPARATORS = charArrayOf(' ', '\t', ':')
@JvmStatic
fun isAsmMnemonic(text: CharSequence) = mnemonics.contains(text.toString().lowercase())
@@ -28,6 +30,11 @@ object LexerUtil {
return text.length - text.indexOfAny(ASSIGNMENT_SEPARATORS)
}
@JvmStatic
fun pushbackAfterFirstToken(text: CharSequence): Int {
return text.length - text.indexOfAny(TOKEN_SEPARATORS)
}
@JvmStatic
fun pushbackLabelColons(text: CharSequence): Int {
return text.count { it == ':' }
@@ -38,7 +45,28 @@ object LexerUtil {
if (!lexer.eatOneWhitespace && lexer.lexerPrefs.spaceIntroducesComment) {
lexer.yybegin(_M68kLexer.WAITEOL)
}
lexer.eatOneWhitespace = false;
lexer.eatOneWhitespace = false
return TokenType.WHITE_SPACE
}
@JvmStatic
fun handleMacroMode(lexer: _M68kLexer): IElementType {
if (lexer.lexerPrefs.macroParametersUnparsed) {
lexer.yybegin(_M68kLexer.MACROCALL)
} else {
lexer.yybegin(_M68kLexer.ASMOPS)
}
lexer.eatOneWhitespace = true
return M68kTypes.MACRO_INVOCATION
}
@JvmStatic
fun handleMacroLineEol(lexer: _M68kLexer): IElementType {
if (++lexer.macroLines > lexer.lexerPrefs.maxLinesPerMacro) {
lexer.yybegin(_M68kLexer.YYINITIAL)
return TokenType.BAD_CHARACTER
}
lexer.yybegin(_M68kLexer.MACROLINE)
return TokenType.WHITE_SPACE
}
}
@@ -2,7 +2,7 @@ package de.platon42.intellij.plugins.m68k.lexer
data class M68kLexerPrefs(
var spaceIntroducesComment: Boolean = false,
var maxLinesPerMacro: Int = 50,
var maxLinesPerMacro: Int = 250,
var macroSectionUnparsed: Boolean = false,
var macroParametersUnparsed: Boolean = true
)
@@ -13,6 +13,9 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
%{
private M68kLexerPrefs lexerPrefs;
boolean eatOneWhitespace = false;
int macroLines = 0;
int exprState = 0;
int exprOpState = 0;
public M68kLexerPrefs getLexerPrefs()
{
@@ -23,6 +26,12 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
this((java.io.Reader)null);
this.lexerPrefs = lexerPrefs;
}
private void startExpr(int newExprState, int newExprOpState) {
exprState = newExprState;
exprOpState = newExprOpState;
yybegin(exprState);
}
%}
%public
@@ -38,10 +47,12 @@ WHITE_SPACE=\p{Blank}+
AREG=(a[0-6])
DREG=(d[0-7])
ASSIGNMENT=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?((\p{Blank}+equ\p{Blank}+)|(\p{Blank}+set\p{Blank}+)|\p{Blank}*=\p{Blank}*))
LOCAL_LABEL=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:?)|(([:letter:]|_)(([:letter:]|[:digit:])|_)*\$:?)
LOCAL_LABEL_WC=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:)|(([:letter:]|_)(([:letter:]|[:digit:])|_)*\$:)
GLOBAL_LABEL=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?:?)
GLOBAL_LABEL_WC=(([:letter:]|_)(([:letter:]|[:digit:])|_)*::?)
LOCAL_LABEL=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:?)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:?)
LOCAL_LABEL_WC=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:)
GLOBAL_LABEL=(([:letter:]|_)([:letter:]|[:digit:]|_)*:?:?)
GLOBAL_LABEL_WC=(([:letter:]|_)([:letter:]|[:digit:]|_)*::?)
MACRO_DEF_LEFT=(([:letter:]|_)(([:letter:]|[:digit:]|_))*)(\p{Blank}+|:\p{Blank}*)macro\p{Blank}*
MACRO_END_TAG=\p{Blank}+endm\p{Blank}*[^;\r\n]*
//MNEMONIC=(([:letter:])+)
SYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$]))*)
BONUSSYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$\.\\]))*)
@@ -51,7 +62,7 @@ OPSIZE_BS=(\.[bs])
OPSIZE_W=(\.w)
OPSIZE_L=(\.l)
BINARY=(%[01]+)
HEXADECIMAL=(\$[0-9a-f]+)
HEXADECIMAL=(\$[0-9a-fA-F]+)
OCTAL=(@[0-7]+)
DECIMAL=([0-9]+)
STRINGLIT=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")
@@ -59,227 +70,159 @@ PLAINPARAM=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")|<([^
COMMENT=([;].*+)
HASH_COMMENT=([#;*].*+)
SKIP_TO_EOL=[^\r\n]+
PLAIN_MACRO_LINE=[^;\r\n]+
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASMOPS_OP,ASSIGNMENT,EXPR,EXPR_OP,MACROCALL,WAITEOL
%state NOSOL,INSTRPART,ASMINSTR,ASMOPS,ASMOPS_OP,ASSIGNMENT,EXPR,EXPR_OP,MACROCALL,WAITEOL,MACRODEF,MACROLINE,MACROTERMINATION,MACROWAITEOL
%%
<YYINITIAL> {
{WHITE_SPACE} { yybegin(NOSOL); eatOneWhitespace = false; return WHITE_SPACE; }
{EOL} { return WHITE_SPACE; }
{ASSIGNMENT} { yybegin(ASSIGNMENT); eatOneWhitespace = true; yypushback(pushbackAssignment(yytext())); return SYMBOLDEF; }
{LOCAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
{HASH_COMMENT} { return COMMENT; }
}
<NOSOL> {
{WHITE_SPACE} { return WHITE_SPACE; }
<YYINITIAL, NOSOL>
{
{EOL} { yybegin(YYINITIAL); return WHITE_SPACE; }
{LOCAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
{DIRECTIVE_KEYWORD} {
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { yybegin(EXPR); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { yybegin(EXPR); return OTHER_DIRECTIVE; }
yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION;
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
{MACRONAME} { yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION; }
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
}
<INSTRPART> {
{WHITE_SPACE} { return WHITE_SPACE; }
<INSTRPART,ASMINSTR,MACROCALL,ASSIGNMENT,EXPR,EXPR_OP,ASMOPS,ASMOPS_OP>
{
{EOL} { yybegin(YYINITIAL); return EOL; }
":" { return COLON; }
{DIRECTIVE_KEYWORD} {
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { yybegin(EXPR); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { yybegin(EXPR); return OTHER_DIRECTIVE; }
yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION;
}
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
{MACRONAME} { yybegin(MACROCALL); eatOneWhitespace = true; return MACRO_INVOKATION; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<NOSOL, INSTRPART, ASSIGNMENT>
{
{WHITE_SPACE} { return WHITE_SPACE; }
}
<MACROCALL, EXPR, EXPR_OP, ASMOPS, ASMOPS_OP> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
}
<YYINITIAL> {
{WHITE_SPACE} { yybegin(NOSOL); eatOneWhitespace = false; return WHITE_SPACE; }
{ASSIGNMENT} { yybegin(ASSIGNMENT); eatOneWhitespace = true; yypushback(pushbackAssignment(yytext())); return SYMBOLDEF; }
{MACRO_DEF_LEFT} { yybegin(MACRODEF); yypushback(pushbackAfterFirstToken(yytext())); return MACRO_NAME; }
{LOCAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL} { yybegin(INSTRPART); eatOneWhitespace = false; yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
}
<NOSOL> {
"macro" { yybegin(MACRODEF); return MACRO_TAG; }
{LOCAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return LOCAL_LABEL_DEF; }
{GLOBAL_LABEL_WC} { yybegin(INSTRPART); yypushback(pushbackLabelColons(yytext())); return GLOBAL_LABEL_DEF; }
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { yybegin(INSTRPART); return SYMBOL; } }
}
<NOSOL, INSTRPART>
{
{DIRECTIVE_KEYWORD} {
if(isAsmMnemonicWithSize(yytext())) { yybegin(ASMINSTR); yypushback(2); return MNEMONIC; }
if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; }
if(isDataDirective(yytext())) { startExpr(EXPR, EXPR_OP); return DATA_DIRECTIVE; }
if(isOtherDirective(yytext())) { startExpr(EXPR, EXPR_OP); return OTHER_DIRECTIVE; }
return handleMacroMode(this);
}
{MACRONAME} { return handleMacroMode(this); }
}
<INSTRPART,MACRODEF> {
":" { return COLON; }
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
}
<ASMINSTR> {
{WHITE_SPACE} { yybegin(ASMOPS); return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
{WHITE_SPACE} { startExpr(ASMOPS, ASMOPS_OP); return WHITE_SPACE; }
{OPSIZE_BS} { return OPSIZE_BS; }
{OPSIZE_W} { return OPSIZE_W; }
{OPSIZE_L} { return OPSIZE_L; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<MACROCALL> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
"," { return SEPARATOR; }
{PLAINPARAM} { return STRINGLIT; }
}
<ASSIGNMENT> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
"equ"|"set" { yybegin(EXPR); return EQU; }
"equ"|"set" { startExpr(EXPR, EXPR_OP); return EQU; }
":" { return COLON; }
"=" { yybegin(EXPR); return OP_ASSIGN; }
"=" { startExpr(EXPR, EXPR_OP); return OP_ASSIGN; }
}
<EXPR, ASMOPS> {
{BINARY} { yybegin(exprOpState); return BINARY; }
{HEXADECIMAL} { yybegin(exprOpState); return HEXADECIMAL; }
{OCTAL} { yybegin(exprOpState); return OCTAL; }
{DECIMAL} { yybegin(exprOpState); return DECIMAL; }
{STRINGLIT} { yybegin(exprOpState); return STRINGLIT; }
"^" { return OP_BITWISE_XOR; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { yybegin(exprOpState); return ROUND_R; }
"!" { return OP_UNARY_NOT; }
"~" { return OP_UNARY_COMPL; }
"+" { return OP_PLUS; }
"-" { return OP_MINUS; }
"*" { yybegin(exprOpState); return CURRENT_PC_SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<EXPR> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{BINARY} { yybegin(EXPR_OP); return BINARY; }
{HEXADECIMAL} { yybegin(EXPR_OP); return HEXADECIMAL; }
{OCTAL} { yybegin(EXPR_OP); return OCTAL; }
{DECIMAL} { yybegin(EXPR_OP); return DECIMAL; }
{STRINGLIT} { yybegin(EXPR_OP); return STRINGLIT; }
"^" { return OP_BITWISE_XOR; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { yybegin(EXPR_OP); return ROUND_R; }
"!" { return OP_UNARY_NOT; }
"~" { return OP_UNARY_COMPL; }
"+" { return OP_PLUS; }
"-" { return OP_MINUS; }
"*" { yybegin(EXPR_OP); return CURRENT_PC_SYMBOL; }
{BONUSSYMBOL} { yybegin(EXPR_OP); return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
{BONUSSYMBOL} { yybegin(exprOpState); return SYMBOL; }
}
<EXPR_OP> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
<EXPR_OP, ASMOPS_OP> {
"<<" { yybegin(exprState); return OP_AR_SHIFT_L; }
">>" { yybegin(exprState); return OP_AR_SHIFT_R; }
"&&" { yybegin(exprState); return OP_LOGICAL_AND; }
"||" { yybegin(exprState); return OP_LOGICAL_OR; }
"=="|"=" { yybegin(exprState); return OP_CMP_EQ; }
"<>"|"!=" { yybegin(exprState); return OP_CMP_NOT_EQ; }
">=" { yybegin(exprState); return OP_CMP_GT_EQ; }
"<=" { yybegin(exprState); return OP_CMP_LT_EQ; }
"<" { yybegin(exprState); return OP_CMP_LT; }
">" { yybegin(exprState); return OP_CMP_GT; }
"&" { yybegin(exprState); return OP_BITWISE_AND; }
"|"|"!" { yybegin(exprState); return OP_BITWISE_OR; }
"^" { yybegin(exprState); return OP_BITWISE_XOR; }
"<<" { yybegin(EXPR); return OP_AR_SHIFT_L; }
">>" { yybegin(EXPR); return OP_AR_SHIFT_R; }
"&&" { yybegin(EXPR); return OP_LOGICAL_AND; }
"||" { yybegin(EXPR); return OP_LOGICAL_OR; }
"=="|"=" { yybegin(EXPR); return OP_CMP_EQ; }
"<>"|"!=" { yybegin(EXPR); return OP_CMP_NOT_EQ; }
">=" { yybegin(EXPR); return OP_CMP_GT_EQ; }
"<=" { yybegin(EXPR); return OP_CMP_LT_EQ; }
"<" { yybegin(EXPR); return OP_CMP_LT; }
">" { yybegin(EXPR); return OP_CMP_GT; }
"&" { yybegin(EXPR); return OP_BITWISE_AND; }
"|"|"!" { yybegin(EXPR); return OP_BITWISE_OR; }
"^" { yybegin(EXPR); return OP_BITWISE_XOR; }
// ":" { return COLON; }
// ";" { return SEMICOLON; }
// "[" { return SQUARE_L; }
// "]" { return SQUARE_R; }
"," { yybegin(EXPR); return SEPARATOR; }
"(" { yybegin(EXPR); return ROUND_L; }
"," { yybegin(exprState); return SEPARATOR; }
"(" { yybegin(exprState); return ROUND_L; }
")" { return ROUND_R; }
// "." { return DOT; }
// "$" { return DOLLAR; }
"~" { yybegin(EXPR); return OP_UNARY_COMPL; }
"+" { yybegin(EXPR); return OP_PLUS; }
"-" { yybegin(EXPR); return OP_MINUS; }
"*" { yybegin(EXPR); return OP_AR_MUL; }
"%"|"//" { yybegin(EXPR); return OP_AR_MOD; }
"/" { yybegin(EXPR); return OP_AR_DIV; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
"~" { yybegin(exprState); return OP_UNARY_COMPL; }
"+" { yybegin(exprState); return OP_PLUS; }
"-" { yybegin(exprState); return OP_MINUS; }
"*" { yybegin(exprState); return OP_AR_MUL; }
"%"|"//" { yybegin(exprState); return OP_AR_MOD; }
"/" { yybegin(exprState); return OP_AR_DIV; }
}
<ASMOPS> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{BINARY} { yybegin(ASMOPS_OP); return BINARY; }
{HEXADECIMAL} { yybegin(ASMOPS_OP); return HEXADECIMAL; }
{OCTAL} { yybegin(ASMOPS_OP); return OCTAL; }
{DECIMAL} { yybegin(ASMOPS_OP); return DECIMAL; }
{STRINGLIT} { yybegin(ASMOPS_OP); return STRINGLIT; }
{AREG} { yybegin(ASMOPS_OP); return AREG; }
{DREG} { yybegin(ASMOPS_OP); return DREG; }
"sp"|"a7" { yybegin(ASMOPS_OP); return REG_SP; }
"pc" { yybegin(ASMOPS_OP); return PC; }
"ccr" { yybegin(ASMOPS_OP); return REG_CCR; }
"sr" { yybegin(ASMOPS_OP); return REG_SR; }
"usp" { yybegin(ASMOPS_OP); return REG_USP; }
"vbr" { yybegin(ASMOPS_OP); return REG_VBR; }
"^" { return OP_BITWISE_XOR; }
"," { return SEPARATOR; }
"(" { return ROUND_L; }
")" { yybegin(ASMOPS_OP); return ROUND_R; }
"!" { return OP_UNARY_NOT; }
"~" { return OP_UNARY_COMPL; }
"+" { return OP_PLUS; }
"-" { return OP_MINUS; }
"*" { yybegin(ASMOPS_OP); return CURRENT_PC_SYMBOL; }
{AREG} { yybegin(exprOpState); return AREG; }
{DREG} { yybegin(exprOpState); return DREG; }
"sp"|"a7" { yybegin(exprOpState); return REG_SP; }
"pc" { yybegin(exprOpState); return PC; }
"ccr" { yybegin(exprOpState); return REG_CCR; }
"sr" { yybegin(exprOpState); return REG_SR; }
"usp" { yybegin(exprOpState); return REG_USP; }
"vbr" { yybegin(exprOpState); return REG_VBR; }
"#" { return HASH; }
{SYMBOL} { yybegin(ASMOPS_OP); return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
{SYMBOL} { yybegin(exprOpState); return SYMBOL; }
}
<ASMOPS_OP> {
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
{EOL} { yybegin(YYINITIAL); return EOL; }
{OPSIZE_BS} { return OPSIZE_BS; }
{OPSIZE_W} { return OPSIZE_W; }
{OPSIZE_L} { return OPSIZE_L; }
"<<" { yybegin(ASMOPS); return OP_AR_SHIFT_L; }
">>" { yybegin(ASMOPS); return OP_AR_SHIFT_R; }
"&&" { yybegin(ASMOPS); return OP_LOGICAL_AND; }
"||" { yybegin(ASMOPS); return OP_LOGICAL_OR; }
"=="|"=" { yybegin(ASMOPS); return OP_CMP_EQ; }
"<>"|"!=" { yybegin(ASMOPS); return OP_CMP_NOT_EQ; }
">=" { yybegin(ASMOPS); return OP_CMP_GT_EQ; }
"<=" { yybegin(ASMOPS); return OP_CMP_LT_EQ; }
"<" { yybegin(ASMOPS); return OP_CMP_LT; }
">" { yybegin(ASMOPS); return OP_CMP_GT; }
"&" { yybegin(ASMOPS); return OP_BITWISE_AND; }
"|"|"!" { yybegin(ASMOPS); return OP_BITWISE_OR; }
"^" { yybegin(ASMOPS); return OP_BITWISE_XOR; }
// ":" { return COLON; }
// ";" { return SEMICOLON; }
// "[" { return SQUARE_L; }
// "]" { return SQUARE_R; }
"," { yybegin(ASMOPS); return SEPARATOR; }
"(" { yybegin(ASMOPS); return ROUND_L; }
")" { return ROUND_R; }
// "." { return DOT; }
// "$" { return DOLLAR; }
"~" { yybegin(ASMOPS); return OP_UNARY_COMPL; }
"+" { yybegin(ASMOPS); return OP_PLUS; }
"-" { yybegin(ASMOPS); return OP_MINUS; }
"*" { yybegin(ASMOPS); return OP_AR_MUL; }
"%"|"//" { yybegin(ASMOPS); return OP_AR_MOD; }
"/" { yybegin(ASMOPS); return OP_AR_DIV; }
{SYMBOL} { return SYMBOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<WAITEOL>
@@ -288,4 +231,35 @@ SKIP_TO_EOL=[^\r\n]+
{SKIP_TO_EOL} { return COMMENT; }
}
// The macro mess starts here
<MACRODEF> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(MACROLINE); macroLines = 0; return WHITE_SPACE; }
"macro" { return MACRO_TAG; }
{MACRONAME} { return MACRO_NAME; }
{COMMENT} { yybegin(MACROWAITEOL); return COMMENT; }
}
<MACROLINE> {
{EOL} { return handleMacroLineEol(this); }
{MACRO_END_TAG} { yybegin(MACROTERMINATION); return MACRO_END_TAG; }
{PLAIN_MACRO_LINE} { return MACRO_LINE; }
{COMMENT} { yybegin(MACROWAITEOL); return COMMENT; }
}
<MACROTERMINATION> {
{WHITE_SPACE} { return WHITE_SPACE; }
{EOL} { yybegin(YYINITIAL); return EOL; }
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
}
<MACROWAITEOL>
{
{EOL} { return handleMacroLineEol(this); }
{SKIP_TO_EOL} { return COMMENT; }
}
[^] { return BAD_CHARACTER; }
@@ -118,7 +118,7 @@
M68kFile ::= line*
private line ::= !<<eof>> statement (<<eof>>|EOL)
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
statement ::= (Assignment
| PreprocessorDirective
@@ -161,16 +161,40 @@ GlobalLabel ::= GLOBAL_LABEL_DEF COLON* {
private Label ::= LocalLabel | GlobalLabel
OperandSize ::= (OPSIZE_BS|OPSIZE_W|OPSIZE_L) { name = ".s|.b|.w|.l" }
OperandSize ::= (OPSIZE_BS|OPSIZE_W|OPSIZE_L) {
name = ".s|.b|.w|.l"
methods = [getSize]
}
AddressSize ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
DataWidth ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
AsmOp ::= MNEMONIC OperandSize?
AsmOp ::= MNEMONIC OperandSize? {
name = "mnemonic"
methods = [getMnemonic getOpSize]
}
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
PreprocessorOperands?
MacroCall ::= MACRO_INVOKATION PlainOperands?
MacroPlainLine ::= MACRO_LINE
MacroNameDefinition ::= MACRO_NAME
MacroDefinition ::= ((MacroNameDefinition COLON? MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG {
pin = 1
name = "macro definition"
implements = "de.platon42.intellij.plugins.m68k.psi.M68kNamedElement"
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinitionMixin"
elementTypeFactory = "de.platon42.intellij.plugins.m68k.stubs.M68kStubElementTypeFactory.stubFactory"
stubClass = "de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub"
methods = [getName setName getNameIdentifier]
}
MacroCall ::= MACRO_INVOCATION PlainOperands? {
mixin = "de.platon42.intellij.plugins.m68k.psi.M68kMacroCallMixin"
methods = [getMacroName]
}
AsmInstruction ::= AsmOp AsmOperands?
private Instruction ::= AsmInstruction | MacroCall
//external Instruction ::= parseMacroCallOrAsmInstruction
@@ -180,7 +204,7 @@ private AsmOperands ::= AddressingMode (SEPARATOR AddressingMode)?
private PreprocessorOperands ::= PreprocessorOperand (SEPARATOR PreprocessorOperand)*
private PreprocessorOperand ::= expr
private PlainOperands ::= STRINGLIT (SEPARATOR STRINGLIT)*
private PlainOperands ::= (expr|AddressingMode) (SEPARATOR (expr|AddressingMode))*
// TODO This should probably be a ILazyParseableElementType, no idea how to implement that yet
SymbolReference ::= SYMBOL {
@@ -210,6 +234,14 @@ Register ::= DataRegister | AddressRegister | SpecialRegister
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
IndexRegister ::= DataOrAddressRegister DataWidth?
{
name = "index register"
methods = [
isLongWidth
]
}
AddressingMode ::= ImmediateData
| AddressRegisterIndirectPreDecAddressingMode
| AddressRegisterIndirectPostIncAddressingMode
@@ -231,20 +263,108 @@ AddressingMode ::= ImmediateData
SpecialRegisterDirectAddressingMode ::= SpecialRegister
DataRegisterDirectAddressingMode ::= DataRegister !(OP_MINUS|OP_AR_DIV)
AddressRegisterDirectAddressingMode ::= AddressRegister !(OP_MINUS|OP_AR_DIV)
AddressRegisterIndirectAddressingMode ::= ROUND_L AddressRegister ROUND_R !OP_PLUS
AddressRegisterIndirectPostIncAddressingMode ::= ROUND_L AddressRegister ROUND_R OP_PLUS
AddressRegisterIndirectPreDecAddressingMode ::= OP_MINUS ROUND_L AddressRegister ROUND_R
AddressRegisterIndirectAddressingMode ::= ROUND_L AddressRegister ROUND_R !OP_PLUS { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
AddressRegisterIndirectPostIncAddressingMode ::= ROUND_L AddressRegister ROUND_R OP_PLUS { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
AddressRegisterIndirectPreDecAddressingMode ::= OP_MINUS ROUND_L AddressRegister ROUND_R { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
AddressRegisterIndirectWithDisplacementOldAddressingMode ::= expr ROUND_L AddressRegister ROUND_R
{
implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
]
methods = [
displacement = "expr"
]
}
AddressRegisterIndirectWithDisplacementNewAddressingMode ::= ROUND_L expr SEPARATOR AddressRegister ROUND_R
AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
{
implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
]
methods = [
displacement = "expr"
]
}
AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegister SEPARATOR IndexRegister ROUND_R
{
implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
]
methods = [
displacement = "expr"
]
}
AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR IndexRegister ROUND_R
{
implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
]
methods = [
displacement = "expr"
]
}
ProgramCounterIndirectWithDisplacementOldAddressingMode ::= (ROUND_L PC ROUND_R) | (expr ROUND_L PC ROUND_R)
{
implements = ["de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"]
methods = [
displacement = "expr"
]
}
ProgramCounterIndirectWithDisplacementNewAddressingMode ::= ROUND_L expr SEPARATOR PC ROUND_R
ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
{
implements = ["de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"]
methods = [
displacement = "expr"
]
}
ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR IndexRegister ROUND_R
{
implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
]
methods = [
displacement = "expr"
]
}
ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? PC SEPARATOR IndexRegister ROUND_R
{
implements = [
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
]
methods = [
displacement = "expr"
]
}
AbsoluteAddressAddressingMode ::= expr AddressSize? !ROUND_L
private RegisterRange ::= (DataOrAddressRegister OP_MINUS DataOrAddressRegister)
RegisterListAddressingMode ::= (DataOrAddressRegister|RegisterRange) ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
RegisterRange ::= (DataRegister OP_MINUS DataRegister) | (AddressRegister OP_MINUS AddressRegister) | (DataRegister OP_MINUS AddressRegister) {
name = "register range"
methods = [
startRegister = "Register[0]"
endRegister = "Register[1]"
]
}
RegisterListAddressingMode ::= (RegisterRange|DataOrAddressRegister) (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
{
name = "register list"
methods = [ getRegisters ]
}
ImmediateData ::= HASH expr {
name = "immediate data"
extends = AddressingMode
@@ -0,0 +1,72 @@
package de.platon42.intellij.plugins.m68k.psi
import de.platon42.intellij.plugins.m68k.asm.*
object M68kAddressModeUtil {
fun getAddressModeForType(addressingMode: M68kAddressingMode?): AddressMode? {
if (addressingMode == null) return null
return when (addressingMode) {
is M68kImmediateData -> AddressMode.IMMEDIATE_DATA
is M68kAddressRegisterIndirectAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT
is M68kAddressRegisterIndirectPostIncAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC
is M68kAddressRegisterIndirectPreDecAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC
is M68kAddressRegisterIndirectWithDisplacementNewAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT
is M68kAddressRegisterIndirectWithDisplacementOldAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT
is M68kAddressRegisterIndirectWithIndexNewAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX
is M68kAddressRegisterIndirectWithIndexOldAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT
is M68kProgramCounterIndirectWithIndexNewAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
is M68kProgramCounterIndirectWithIndexOldAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
is M68kSpecialRegisterDirectAddressingMode -> AddressMode.SPECIAL_REGISTER_DIRECT
is M68kDataRegisterDirectAddressingMode -> AddressMode.DATA_REGISTER_DIRECT
is M68kAddressRegisterDirectAddressingMode -> AddressMode.ADDRESS_REGISTER_DIRECT
is M68kRegisterListAddressingMode -> AddressMode.REGISTER_LIST
is M68kAbsoluteAddressAddressingMode -> AddressMode.ABSOLUTE_ADDRESS
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode")
}
}
fun getOtherReadWriteModifyRegisters(rwm: Int): List<Pair<Register, Int>> {
if (rwm and RWM_MODIFY_STACK > 0) {
return listOf(Register.A7 to RWM_MODIFY_L)
}
return emptyList()
}
fun getReadWriteModifyRegisters(addressingMode: M68kAddressingMode?, rwm: Int): List<Pair<Register, Int>> {
if (addressingMode == null) return emptyList()
return when (addressingMode) {
is M68kImmediateData,
is M68kSpecialRegisterDirectAddressingMode,
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode,
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode,
is M68kAbsoluteAddressAddressingMode -> emptyList()
is M68kAddressRegisterIndirectPostIncAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_L)
is M68kAddressRegisterIndirectPreDecAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_MODIFY_L)
is M68kWithAddressRegisterIndirect -> {
if (addressingMode is M68kWithIndexRegister) {
listOf(
Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_L,
Register.getRegFromName(addressingMode.indexRegister.register.text) to if (addressingMode.indexRegister.isLongWidth) RWM_READ_L else RWM_READ_W
)
} else {
listOf(Register.getRegFromName(addressingMode.addressRegister.text) to RWM_READ_L)
}
}
is M68kWithIndexRegister -> listOf(Register.getRegFromName(addressingMode.indexRegister.register.text) to if (addressingMode.indexRegister.isLongWidth) RWM_READ_L else RWM_READ_W)
is M68kDataRegisterDirectAddressingMode -> listOf(Register.getRegFromName(addressingMode.dataRegister.text) to rwm)
is M68kAddressRegisterDirectAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to rwm)
is M68kRegisterListAddressingMode -> addressingMode.registers.map { it to rwm }
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode")
}
}
fun mergeReadWriteModifyRegisters(regset: Set<Pair<Register, Int>>): Set<Pair<Register, Int>> {
if (regset.size <= 1) return regset
return regset.groupBy({ it.first }) { it.second }
.map { it.key to if (it.value.size == 1) it.value.single() else it.value.reduce(Int::or) }
.toSet()
}
}
@@ -27,6 +27,16 @@ object M68kElementFactory {
return PsiTreeUtil.findChildOfType(file, M68kSymbolReference::class.java)!!
}
fun createMacroDefinition(project: Project, name: String): M68kMacroDefinition {
val file = createFile(project, "$name macro\nendm\n")
return PsiTreeUtil.findChildOfType(file, M68kMacroDefinition::class.java)!!
}
fun createMacroCall(project: Project, name: String): M68kMacroCall {
val file = createFile(project, " $name\n")
return PsiTreeUtil.findChildOfType(file, M68kMacroCall::class.java)!!
}
fun createFile(project: Project, content: String): M68kFile {
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as M68kFile
}
@@ -5,6 +5,7 @@ import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
object M68kLookupUtil {
@@ -93,4 +94,47 @@ object M68kLookupUtil {
}
fun findAllSymbolDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
fun findAllMacroDefinitions(project: Project): List<M68kMacroDefinition> {
val results: MutableList<M68kMacroDefinition> = ArrayList()
StubIndex.getInstance().processAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
{
results.addAll(
StubIndex.getElements(
M68kMacroDefinitionStubIndex.KEY,
it,
project,
GlobalSearchScope.allScope(project),
M68kMacroDefinition::class.java
)
)
true
}
return results
}
fun findAllMacroDefinitions(file: M68kFile): List<M68kMacroDefinition> {
val results: MutableList<M68kMacroDefinition> = ArrayList()
StubIndex.getInstance().processAllKeys(
M68kMacroDefinitionStubIndex.KEY,
{
results.addAll(
StubIndex.getElements(
M68kMacroDefinitionStubIndex.KEY,
it,
file.project,
GlobalSearchScope.fileScope(file),
M68kMacroDefinition::class.java
)
)
true
}, GlobalSearchScope.fileScope(file), null
)
return results
}
fun findAllMacroDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
}
@@ -0,0 +1,13 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.ASTWrapperPsiElement
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiReference
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
abstract class M68kMacroCallMixin(node: ASTNode) : ASTWrapperPsiElement(node), M68kMacroCall {
override fun getReferences(): Array<PsiReference> {
return ReferenceProvidersRegistry.getReferencesFromProviders(this)
}
}
@@ -0,0 +1,29 @@
package de.platon42.intellij.plugins.m68k.psi
import com.intellij.extapi.psi.StubBasedPsiElementBase
import com.intellij.ide.projectView.PresentationData
import com.intellij.lang.ASTNode
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.stubs.IStubElementType
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub
import javax.swing.Icon
abstract class M68kMacroDefinitionMixin : StubBasedPsiElementBase<M68kMacroDefinitionStub>, M68kMacroDefinition {
constructor(node: ASTNode) : super(node)
constructor(stub: M68kMacroDefinitionStub, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
override fun getPresentation(): ItemPresentation? {
return PresentationData(name, containingFile.name, getIcon(0), null)
}
override fun getIcon(flags: Int): Icon? {
return M68kIcons.MACRO_DEF
}
override fun toString(): String {
return javaClass.simpleName + "(MACRO_DEFINITION)"
}
}
@@ -2,8 +2,10 @@ package de.platon42.intellij.plugins.m68k.psi
import com.intellij.psi.PsiElement
import com.intellij.util.IncorrectOperationException
import de.platon42.intellij.plugins.m68k.asm.*
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createSymbolDefinition
object M68kPsiImplUtil {
@@ -71,4 +73,71 @@ object M68kPsiImplUtil {
val text = element.firstChild.text
return text.startsWith('.') || text.endsWith('$')
}
}
// Macro Definition
@JvmStatic
fun getName(element: M68kMacroDefinition): String? = element.macroNameDefinition.firstChild.text
@JvmStatic
fun setName(element: M68kMacroDefinition, name: String): PsiElement {
val nameNode = element.macroNameDefinition
val newMacroDefinition = createMacroDefinition(element.project, name)
nameNode.replace(newMacroDefinition.firstChild)
return element
}
@JvmStatic
fun getNameIdentifier(element: M68kMacroDefinition): PsiElement = element.firstChild
// Macro Call
@JvmStatic
fun getMacroName(element: M68kMacroCall): String = element.firstChild.text
// AsmOp
@JvmStatic
fun getMnemonic(element: M68kAsmOp): String = element.firstChild.text
@JvmStatic
fun getOpSize(element: M68kAsmOp): Int = element.operandSize?.size ?: OP_UNSIZED
// OperandSize
@JvmStatic
fun getSize(element: M68kOperandSize): Int =
when (element.text) {
null -> OP_UNSIZED
".w" -> OP_SIZE_W
".l" -> OP_SIZE_L
".b" -> OP_SIZE_B
".s" -> OP_SIZE_S
else -> throw IllegalArgumentException("Unknown op size ${element.text}")
}
// RegisterListAddressingMode
@JvmStatic
fun getRegisters(element: M68kRegisterListAddressingMode): Set<Register> {
val registers: MutableSet<Register> = HashSet()
element.registerList.forEach { registers.add(Register.getRegFromName(it.text)) }
element.registerRangeList.forEach {
var startReg = Register.getRegFromName(it.startRegister.text)
val endReg = Register.getRegFromName(it.endRegister!!.text)
registers.add(startReg)
while ((startReg.num < endReg.num) || (startReg.regname.dropLast(1) != endReg.regname.dropLast(1))) {
startReg = if (startReg.num < 7) {
Register.getRegFromName(startReg.regname.dropLast(1) + (startReg.num + 1))
} else {
Register.A0 // handle wrap around from d7->a0
}
registers.add(startReg)
}
}
return registers
}
// IndexRegister
@JvmStatic
fun isLongWidth(element: M68kIndexRegister): Boolean {
return element.dataWidth?.text.equals(".l", ignoreCase = true)
}
}
@@ -13,12 +13,13 @@ class M68kRenameInputValidator : RenameInputValidator {
override fun getPattern(): ElementPattern<out PsiElement?> = StandardPatterns.or(
PlatformPatterns.psiElement(M68kGlobalLabel::class.java),
PlatformPatterns.psiElement(M68kLocalLabel::class.java),
PlatformPatterns.psiElement(M68kSymbolDefinition::class.java)
PlatformPatterns.psiElement(M68kSymbolDefinition::class.java),
PlatformPatterns.psiElement(M68kMacroDefinition::class.java)
)
override fun isInputValid(newName: String, element: PsiElement, context: ProcessingContext): Boolean {
return when (element) {
is M68kGlobalLabel, is M68kSymbolDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
is M68kGlobalLabel, is M68kSymbolDefinition, is M68kMacroDefinition -> SYMBOL_PATTERN.matcher(newName).matches()
is M68kLocalLabel -> LOCAL_LABEL_PATTERN.matcher(newName).matches()
else -> false
}
@@ -0,0 +1,6 @@
package de.platon42.intellij.plugins.m68k.psi
interface M68kWithAddressRegisterIndirect : M68kAddressingMode {
val addressRegister: M68kAddressRegister
}
@@ -0,0 +1,6 @@
package de.platon42.intellij.plugins.m68k.psi
interface M68kWithDisplacement : M68kAddressingMode {
val displacement: M68kExpr?
}
@@ -0,0 +1,6 @@
package de.platon42.intellij.plugins.m68k.psi
interface M68kWithIndexRegister : M68kAddressingMode {
val indexRegister: M68kIndexRegister
}
@@ -1,8 +1,7 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.navigation.ChooseByNameContributorEx2
import com.intellij.navigation.ChooseByNameContributorEx
import com.intellij.navigation.NavigationItem
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.Processor
@@ -13,17 +12,17 @@ import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
class M68kChooseByNameContributor : ChooseByNameContributorEx2 {
class M68kChooseByNameContributor : ChooseByNameContributorEx {
override fun processNames(processor: Processor<in String>, parameters: FindSymbolParameters) {
processNames(processor, parameters.searchScope, parameters.idFilter)
}
// override fun processNames(processor: Processor<in String>, parameters: FindSymbolParameters) {
// processNames(processor, parameters.searchScope, parameters.idFilter)
// }
override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
val result: MutableList<NavigationItem> = ArrayList()
processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
return result.toTypedArray()
}
// override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
// val result: MutableList<NavigationItem> = ArrayList()
// processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
// return result.toTypedArray()
// }
override fun processNames(processor: Processor<in String>, scope: GlobalSearchScope, filter: IdFilter?) {
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, processor, scope, filter)
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.icons.AllIcons
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
@@ -18,7 +18,7 @@ class M68kGlobalLabelSymbolCompletionContributor : CompletionContributor() {
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
"pc"
)
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(AllIcons.Nodes.Record).withBoldness(true), 2.0) }
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
}
init {
@@ -7,12 +7,14 @@ import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiSearchHelper
import com.intellij.psi.search.UsageSearchContext
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kNamedElement
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
@@ -24,18 +26,23 @@ class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
class Resolver : ResolveCache.PolyVariantResolver<M68kGlobalLabelSymbolReference> {
override fun resolve(ref: M68kGlobalLabelSymbolReference, incompleteCode: Boolean): Array<ResolveResult> {
val refName = ref.element.symbolName
val project = ref.element.project
val targets: MutableList<PsiElement> = SmartList()
PsiSearchHelper.getInstance(project).processElementsWithWord(
{ elem, _ ->
when (elem) {
is M68kGlobalLabel, is M68kSymbolDefinition -> targets.add(elem)
}
val targets: MutableList<M68kNamedElement> = SmartList()
StubIndex.getInstance()
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
{
targets.add(it)
true
}, GlobalSearchScope.allScope(project),
refName, UsageSearchContext.IN_CODE, true
)
}
StubIndex.getInstance()
.processElements(M68kSymbolDefinitionStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kSymbolDefinition::class.java)
{
targets.add(it)
true
}
return targets
.map(::PsiElementResolveResult)
.toTypedArray()
@@ -0,0 +1,19 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
class M68kMacroCallCompletionContributor : CompletionContributor() {
init {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.MACRO_INVOCATION), object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
resultSet.addAllElements(M68kLookupUtil.findAllMacroDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
}
})
}
}
@@ -0,0 +1,17 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.openapi.util.TextRange
import com.intellij.psi.AbstractElementManipulator
import com.intellij.util.IncorrectOperationException
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
class M68kMacroCallElementManipulator : AbstractElementManipulator<M68kMacroCall>() {
@Throws(IncorrectOperationException::class)
override fun handleContentChange(element: M68kMacroCall, range: TextRange, newContent: String): M68kMacroCall {
val newMacroCall = M68kElementFactory.createMacroCall(element.project, newContent)
element.firstChild.replace(newMacroCall.firstChild)
return element
}
}
@@ -0,0 +1,49 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementResolveResult
import com.intellij.psi.PsiPolyVariantReferenceBase
import com.intellij.psi.ResolveResult
import com.intellij.psi.impl.source.resolve.ResolveCache
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.SmartList
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
class M68kMacroReference(element: M68kMacroCall) :
PsiPolyVariantReferenceBase<M68kMacroCall>(element, TextRange(0, element.macroName.length)) {
companion object {
val INSTANCE = Resolver()
}
class Resolver : ResolveCache.PolyVariantResolver<M68kMacroReference> {
override fun resolve(ref: M68kMacroReference, incompleteCode: Boolean): Array<ResolveResult> {
val macroName = ref.element.macroName
val project = ref.element.project
val targets: MutableList<M68kMacroDefinition> = SmartList()
StubIndex.getInstance()
.processElements(M68kMacroDefinitionStubIndex.KEY, macroName, project, GlobalSearchScope.allScope(project), M68kMacroDefinition::class.java)
{
targets.add(it)
true
}
return targets
.map(::PsiElementResolveResult)
.toTypedArray()
}
}
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> =
ResolveCache.getInstance(element.project)
.resolveWithCaching(this, INSTANCE, false, incompleteCode)
override fun resolve(): PsiElement? = multiResolve(false).singleOrNull()?.element
override fun getVariants(): Array<Any> = emptyArray()
}
@@ -3,6 +3,7 @@ package de.platon42.intellij.plugins.m68k.refs
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.*
import com.intellij.util.ProcessingContext
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
class M68kReferenceContributor : PsiReferenceContributor() {
@@ -10,11 +11,13 @@ class M68kReferenceContributor : PsiReferenceContributor() {
companion object {
val localLabelReferenceProvider = LocalLabelReferenceProvider()
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
val macroReferenceProvider = MacroReferenceProvider()
}
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kMacroCall::class.java), macroReferenceProvider)
}
class LocalLabelReferenceProvider : PsiReferenceProvider() {
@@ -32,4 +35,9 @@ class M68kReferenceContributor : PsiReferenceContributor() {
return arrayOf(M68kGlobalLabelSymbolReference(symbolReference))
}
}
class MacroReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> =
arrayOf(M68kMacroReference(element as M68kMacroCall))
}
}
@@ -16,7 +16,7 @@ class M68kFindUsagesProvider : FindUsagesProvider {
override fun getWordsScanner(): WordsScanner =
DefaultWordsScanner(
M68kLexer(M68kLexerPrefs()), // FIXME Oh no! More Prefs!
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.SYMBOL),
TokenSet.create(M68kTypes.SYMBOLDEF, M68kTypes.GLOBAL_LABEL_DEF, M68kTypes.LOCAL_LABEL_DEF, M68kTypes.MACRO_NAME),
TokenSet.create(M68kTypes.COMMENT),
TokenSet.create(M68kTypes.STRINGLIT, M68kTypes.DECIMAL, M68kTypes.HEXADECIMAL, M68kTypes.OCTAL, M68kTypes.BINARY),
TokenSet.EMPTY
@@ -32,6 +32,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kLocalLabel -> "local label"
is M68kSymbolDefinition -> "symbol definition"
is M68kSymbolReference -> "symbol reference"
is M68kMacroDefinition -> "macro definition"
is M68kMacroCall -> "macro call"
is M68kRegister -> "register"
is M68kRefExpr -> "reference expression"
else -> ""
@@ -44,6 +46,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
is M68kLocalLabel -> element.name!!
is M68kSymbolDefinition -> element.parent.text
is M68kSymbolReference -> element.symbolName
is M68kMacroDefinition -> element.macroNameDefinition.text
is M68kMacroCall -> element.macroName
is M68kRefExpr -> element.symbolReference?.symbolName ?: ""
is M68kRegister -> element.text
else -> ""
@@ -4,7 +4,6 @@ import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.ide.util.treeView.smartTree.TreeElement
import com.intellij.navigation.ItemPresentation
import com.intellij.psi.NavigatablePsiElement
import com.intellij.refactoring.suggested.startOffset
import de.platon42.intellij.plugins.m68k.psi.M68kFile
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
@@ -19,8 +18,9 @@ class M68kStructureViewElement(private val myElement: NavigatablePsiElement) : S
return when (myElement) {
is M68kFile -> {
listOf(
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.startOffset },
M68kLookupUtil.findAllGlobalLabels(myElement).sortedBy { it.startOffset },
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.textRange.startOffset },
M68kLookupUtil.findAllMacroDefinitions(myElement).sortedBy { it.textRange.startOffset },
M68kLookupUtil.findAllGlobalLabels(myElement).sortedBy { it.textRange.startOffset },
// M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! }),
// M68kLookupUtil.findAllGlobalLabels(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! })
)
@@ -3,23 +3,77 @@ package de.platon42.intellij.plugins.m68k.structureview
import com.intellij.ide.structureView.StructureViewModel.ElementInfoProvider
import com.intellij.ide.structureView.StructureViewModelBase
import com.intellij.ide.structureView.StructureViewTreeElement
import com.intellij.ide.util.treeView.smartTree.Sorter
import com.intellij.ide.util.treeView.smartTree.*
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiFile
import de.platon42.intellij.plugins.m68k.M68kIcons
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider {
override fun isAlwaysShowsPlus(element: StructureViewTreeElement): Boolean {
return false
companion object {
val FILTERS = arrayOf(SymbolsFilter(), MacrosFilter(), GlobalLabelFilter(), LocalLabelFilter())
const val SYMBOLS_FILTER_ID = "SHOW_SYMBOLS"
const val MACROS_FILTER_ID = "SHOW_MACROS"
const val GLOBAL_LABEL_FILTER_ID = "SHOW_GLOBAL_LABELS"
const val LOCAL_LABEL_FILTER_ID = "SHOW_LOCAL_LABELS"
}
override fun isAlwaysShowsPlus(element: StructureViewTreeElement): Boolean = false
override fun isAlwaysLeaf(element: StructureViewTreeElement): Boolean {
return element.value is M68kLocalLabel
return when (element.value) {
is M68kLocalLabel, is M68kMacroDefinition, is M68kSymbolDefinition -> true
else -> false
}
}
override fun getSorters(): Array<Sorter> {
return arrayOf(Sorter.ALPHA_SORTER)
override fun getSorters(): Array<Sorter> = arrayOf(Sorter.ALPHA_SORTER)
override fun getFilters(): Array<Filter> = FILTERS
class SymbolsFilter : Filter {
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Symbols", null, M68kIcons.SYMBOL_DEF)
override fun getName(): String = SYMBOLS_FILTER_ID
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kSymbolDefinition
override fun isReverted() = true
}
class MacrosFilter : Filter {
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Macros", null, M68kIcons.MACRO_DEF)
override fun getName(): String = MACROS_FILTER_ID
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kMacroDefinition
override fun isReverted() = true
}
class GlobalLabelFilter : Filter {
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Global Labels", null, M68kIcons.GLOBAL_LABEL)
override fun getName(): String = GLOBAL_LABEL_FILTER_ID
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kGlobalLabel
override fun isReverted() = true
}
class LocalLabelFilter : Filter {
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Local Labels", null, M68kIcons.LOCAL_LABEL)
override fun getName(): String = LOCAL_LABEL_FILTER_ID
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kLocalLabel
override fun isReverted() = true
}
}
@@ -8,11 +8,14 @@ import com.intellij.psi.stubs.*
import com.intellij.psi.tree.ILightStubFileElementType
import de.platon42.intellij.plugins.m68k.MC68000Language.Companion.INSTANCE
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
import de.platon42.intellij.plugins.m68k.psi.impl.M68kGlobalLabelImpl
import de.platon42.intellij.plugins.m68k.psi.impl.M68kMacroDefinitionImpl
import de.platon42.intellij.plugins.m68k.psi.impl.M68kSymbolDefinitionImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kGlobalLabelStubImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kMacroDefinitionStubImpl
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kSymbolDefinitionStubImpl
import java.io.IOException
@@ -67,5 +70,28 @@ interface M68kElementTypes {
override fun indexStub(stub: M68kSymbolDefinitionStub, sink: IndexSink) = sink.occurrence(M68kSymbolDefinitionStubIndex.KEY, stub.name!!)
}
@JvmField
val MACRO_DEFINITION: IStubElementType<M68kMacroDefinitionStub, M68kMacroDefinition> =
object : M68kStubElementType<M68kMacroDefinitionStub, M68kMacroDefinition>("MACRO_DEFINITION") {
override fun createPsi(stub: M68kMacroDefinitionStub): M68kMacroDefinition = M68kMacroDefinitionImpl(stub, this)
override fun createStub(psi: M68kMacroDefinition, parentStub: StubElement<out PsiElement>): M68kMacroDefinitionStub =
M68kMacroDefinitionStubImpl(parentStub, this, psi.name!!)
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): M68kMacroDefinitionStub {
val idNode = LightTreeUtil.requiredChildOfType(tree, node, M68kTypes.MACRO_NAME_DEFINITION)
return M68kMacroDefinitionStubImpl(parentStub, this, LightTreeUtil.toFilteredString(tree, idNode, null))
}
@Throws(IOException::class)
override fun serialize(stub: M68kMacroDefinitionStub, dataStream: StubOutputStream) = dataStream.writeName(stub.name)
@Throws(IOException::class)
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): M68kMacroDefinitionStub =
M68kMacroDefinitionStubImpl(parentStub, this, dataStream.readName()!!)
override fun indexStub(stub: M68kMacroDefinitionStub, sink: IndexSink) = sink.occurrence(M68kMacroDefinitionStubIndex.KEY, stub.name!!)
}
}
}
@@ -0,0 +1,6 @@
package de.platon42.intellij.plugins.m68k.stubs
import com.intellij.psi.stubs.NamedStub
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
interface M68kMacroDefinitionStub : NamedStub<M68kMacroDefinition>
@@ -0,0 +1,16 @@
package de.platon42.intellij.plugins.m68k.stubs
import com.intellij.psi.stubs.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndexKey
import de.platon42.intellij.plugins.m68k.M68kFileElementType
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
class M68kMacroDefinitionStubIndex : StringStubIndexExtension<M68kMacroDefinition>() {
override fun getKey(): StubIndexKey<String, M68kMacroDefinition> = KEY
override fun getVersion(): Int = M68kFileElementType.STUB_VERSION
companion object {
val KEY = StubIndexKey.createIndexKey<String, M68kMacroDefinition>("mc68000.macrodef.index")
}
}
@@ -10,6 +10,7 @@ object M68kStubElementTypeFactory {
return when (name) {
"GLOBAL_LABEL" -> M68kElementTypes.GLOBAL_LABEL
"SYMBOL_DEFINITION" -> M68kElementTypes.SYMBOL_DEFINITION
"MACRO_DEFINITION" -> M68kElementTypes.MACRO_DEFINITION
else -> throw RuntimeException("Unknown element type '$name'")
}
}
@@ -0,0 +1,13 @@
package de.platon42.intellij.plugins.m68k.stubs.impl
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.NamedStubBase
import com.intellij.psi.stubs.StubElement
import com.intellij.util.io.StringRef
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStub
class M68kMacroDefinitionStubImpl : NamedStubBase<M68kMacroDefinition>, M68kMacroDefinitionStub {
constructor(parent: StubElement<*>, elementType: IStubElementType<*, *>, name: StringRef) : super(parent, elementType, name)
constructor(parent: StubElement<*>, elementType: IStubElementType<*, *>, name: String) : super(parent, elementType, name)
}
@@ -18,6 +18,9 @@ import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.GLOBAL_LABEL
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.LOCAL_LABEL
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_CALL
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_LINE
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_NAME_DEF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MACRO_PREPROCESSOR
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.MNEMONIC
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.NUMBER
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.OTHER_PREPROCESSOR
@@ -26,8 +29,8 @@ import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SPECIAL_REG
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.STACK_POINTER
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.STRING
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLDEF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLREF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL_DEF
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL_REF
import org.jetbrains.annotations.NonNls
import javax.swing.Icon
@@ -49,7 +52,7 @@ PIC_HEIGHT = 256
include "../includes/hardware/custom.i"
BLTHOGON MACRO ; macro definition
move.w #DMAF_SETCLR|DMAF_BLITHOG,dmacon(a5)
move.w #DMAF_SETCLR|DMAF_BLITHOG,dmacon(a5) ; hog!
ENDM
demo_init ; global label
@@ -99,9 +102,12 @@ hello: dc.b 'Hello World!',10,0
AttributesDescriptor("Local labels", LOCAL_LABEL),
AttributesDescriptor("Comma (separator)", SEPARATOR),
AttributesDescriptor("Colon", COLON),
AttributesDescriptor("Symbol definition", SYMBOLDEF),
AttributesDescriptor("Symbol reference", SYMBOLREF),
AttributesDescriptor("Symbol definition", SYMBOL_DEF),
AttributesDescriptor("Symbol reference", SYMBOL_REF),
AttributesDescriptor("Assembly mnemonic", MNEMONIC),
AttributesDescriptor("Macro name definition", MACRO_NAME_DEF),
AttributesDescriptor("Macro preprocessor directives", MACRO_PREPROCESSOR),
AttributesDescriptor("Macro line", MACRO_LINE),
AttributesDescriptor("Macro invocation", MACRO_CALL),
AttributesDescriptor("Data width: Byte/short", DATA_WIDTH_BS),
AttributesDescriptor("Data width: Word", DATA_WIDTH_W),
@@ -28,11 +28,14 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
M68kTypes.COLON -> arrayOf(COLON)
M68kTypes.GLOBAL_LABEL_DEF -> arrayOf(GLOBAL_LABEL)
M68kTypes.LOCAL_LABEL_DEF -> arrayOf(LOCAL_LABEL)
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOLDEF)
M68kTypes.SYMBOL -> arrayOf(SYMBOLREF)
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOL_DEF)
M68kTypes.SYMBOL -> arrayOf(SYMBOL_REF)
M68kTypes.CURRENT_PC_SYMBOL, M68kTypes.PC -> arrayOf(PROGRAM_COUNTER)
M68kTypes.MNEMONIC -> arrayOf(MNEMONIC)
M68kTypes.MACRO_INVOKATION -> arrayOf(MACRO_CALL)
M68kTypes.MACRO_TAG, M68kTypes.MACRO_END_TAG -> arrayOf(MACRO_PREPROCESSOR)
M68kTypes.MACRO_LINE -> arrayOf(MACRO_LINE)
M68kTypes.MACRO_INVOCATION -> arrayOf(MACRO_CALL)
M68kTypes.MACRO_NAME -> arrayOf(MACRO_NAME_DEF)
M68kTypes.DATA_DIRECTIVE -> arrayOf(DATA_PREPROCESSOR)
M68kTypes.OTHER_DIRECTIVE, M68kTypes.EQU -> arrayOf(OTHER_PREPROCESSOR)
M68kTypes.OPSIZE_BS -> arrayOf(DATA_WIDTH_BS)
@@ -55,9 +58,12 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
val LOCAL_LABEL = TextAttributesKey.createTextAttributesKey("MC68000_GLOBAL_LABEL", DefaultLanguageHighlighterColors.FUNCTION_DECLARATION)
val SEPARATOR = TextAttributesKey.createTextAttributesKey("MC68000_SEPARATOR", DefaultLanguageHighlighterColors.COMMA)
val COLON = TextAttributesKey.createTextAttributesKey("MC68000_COLON", DefaultLanguageHighlighterColors.DOT)
val SYMBOLDEF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLDEF", DefaultLanguageHighlighterColors.CONSTANT)
val SYMBOLREF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
val SYMBOL_DEF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLDEF", DefaultLanguageHighlighterColors.CONSTANT)
val SYMBOL_REF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
val MNEMONIC = TextAttributesKey.createTextAttributesKey("MC68000_MNEMONIC", DefaultLanguageHighlighterColors.FUNCTION_CALL)
val MACRO_PREPROCESSOR = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_PREPROCESSOR", DefaultLanguageHighlighterColors.INSTANCE_METHOD)
val MACRO_NAME_DEF = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_NAME_DEF", DefaultLanguageHighlighterColors.METADATA)
val MACRO_LINE = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_LINE", DefaultLanguageHighlighterColors.METADATA)
val MACRO_CALL = TextAttributesKey.createTextAttributesKey("MC68000_MACRO_CALL", DefaultLanguageHighlighterColors.STATIC_METHOD)
val DATA_WIDTH_BS = TextAttributesKey.createTextAttributesKey("MC68000_DATA_WIDTH_BS", DefaultLanguageHighlighterColors.DOT)
val DATA_WIDTH_L = TextAttributesKey.createTextAttributesKey("MC68000_DATA_WIDTH_W", DefaultLanguageHighlighterColors.DOT)
@@ -0,0 +1,100 @@
package de.platon42.intellij.plugins.m68k.utils
import de.platon42.intellij.plugins.m68k.asm.*
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
import de.platon42.intellij.plugins.m68k.psi.M68kSpecialRegisterDirectAddressingMode
object M68kIsaUtil {
// TODO if more than one result, do a check and consolidate
fun findExactIsaDataForInstruction(asmInstruction: M68kAsmInstruction): IsaData? =
findIsaDataForInstruction(asmInstruction).firstOrNull()?.first
// TODO if more than one result, do a check and consolidate
fun findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction: M68kAsmInstruction): Pair<IsaData, AllowedAdrMode>? {
val (isaData, adrModeList) = findIsaDataForInstruction(asmInstruction).firstOrNull() ?: return null
return isaData to adrModeList.first()
}
fun findIsaDataForInstruction(asmInstruction: M68kAsmInstruction): List<Pair<IsaData, List<AllowedAdrMode>>> {
val isaDataCandidates = M68kIsa.findMatchingInstructions(asmInstruction.asmOp.mnemonic)
if (isaDataCandidates.isEmpty()) return emptyList()
val amOp1 = asmInstruction.addressingModeList.getOrNull(0)
val amOp2 = asmInstruction.addressingModeList.getOrNull(1)
val op1 = M68kAddressModeUtil.getAddressModeForType(amOp1)
val op2 = M68kAddressModeUtil.getAddressModeForType(amOp2)
val specialReg1 = (amOp1 as? M68kSpecialRegisterDirectAddressingMode)?.specialRegister?.text
val specialReg2 = (amOp2 as? M68kSpecialRegisterDirectAddressingMode)?.specialRegister?.text
val specialReg = specialReg1 ?: specialReg2
val opSize = asmInstruction.asmOp.opSize
val matchedIsaData =
M68kIsa.findMatchingOpMode(isaDataCandidates, op1, op2, opSize, specialReg)
return matchedIsaData.map { it to M68kIsa.findMatchingAddressMode(it.modes, op1, op2, opSize, specialReg) }
}
fun getOpSizeOrDefault(opSize: Int, adrMode: AllowedAdrMode): Int {
if (opSize == OP_UNSIZED && (adrMode.size != OP_UNSIZED)) {
return if ((adrMode.size and OP_SIZE_W) == OP_SIZE_W) {
OP_SIZE_W
} else {
adrMode.size
}
}
return opSize
}
fun modifyRwmWithOpsize(rwm: Int, opSize: Int): Int {
if (opSize == OP_UNSIZED) return rwm
return when (rwm) {
RWM_READ_OPSIZE -> when (opSize) {
OP_SIZE_B -> RWM_READ_B
OP_SIZE_W -> RWM_READ_W
OP_SIZE_L -> RWM_READ_L
else -> rwm
}
RWM_MODIFY_OPSIZE -> when (opSize) {
OP_SIZE_B -> RWM_MODIFY_B
OP_SIZE_W -> RWM_MODIFY_W
OP_SIZE_L -> RWM_MODIFY_L
else -> rwm
}
RWM_SET_OPSIZE -> when (opSize) {
OP_SIZE_B -> RWM_SET_B
OP_SIZE_W -> RWM_SET_W
OP_SIZE_L -> RWM_SET_L
else -> rwm
}
else -> rwm
}
}
fun findOpSizeDescription(opSize: Int): String {
return when (opSize) {
OP_UNSIZED -> ""
OP_SIZE_B -> ".b"
OP_SIZE_W -> ".w"
OP_SIZE_L -> ".l"
OP_SIZE_S -> ".s"
OP_SIZE_BWL -> ".b|.w|.l"
OP_SIZE_WL -> ".w|.l"
OP_SIZE_SBW -> ".s|.b|.w"
else -> "?"
}
}
fun findOpSizeDescriptions(opSize: Int): List<String> {
return when (opSize) {
OP_UNSIZED -> listOf("")
OP_SIZE_B -> listOf(".b")
OP_SIZE_W -> listOf(".w")
OP_SIZE_L -> listOf(".l")
OP_SIZE_S -> listOf(".s")
OP_SIZE_BWL -> listOf(".b", ".w", ".l")
OP_SIZE_WL -> listOf(".w", ".l")
OP_SIZE_SBW -> listOf(".s", ".b", ".w")
else -> listOf("?")
}
}
}
+15 -1
View File
@@ -10,7 +10,7 @@
<p>
<a href="https://github.com/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
]]></description>
<idea-version since-build="193.7288.0"/>
<idea-version since-build="203.5981.166"/>
<depends>com.intellij.modules.lang</depends>
@@ -24,18 +24,32 @@
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.asm.M68kMnemonicCompletionContributor"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kGlobalLabelSymbolCompletionContributor"/>
<completion.contributor language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallCompletionContributor"/>
<lang.braceMatcher language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kPairedBraceMatcher"/>
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
<lang.findUsagesProvider language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.scanner.M68kFindUsagesProvider"/>
<lang.psiStructureViewFactory language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.structureview.M68kStructureViewFactory"/>
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kMacroCall"
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallElementManipulator"/>
<lang.documentationProvider language="MC68000"
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kSymbolDefinitionDocumentationProvider"/>
<lang.documentationProvider language="MC68000"
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kRegisterFlowDocumentationProvider"/>
<lang.documentationProvider language="MC68000"
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kInstructionDocumentationProvider"/>
<stubElementTypeHolder class="de.platon42.intellij.plugins.m68k.stubs.M68kElementTypes"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex"/>
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/>
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kSyntaxInspection"
displayName="Assembly instruction validity" groupName="M68k"
enabledByDefault="true" level="ERROR"/>
</extensions>
<actions>
@@ -0,0 +1,14 @@
<html>
<body>
Reports wrong use of assembler instruction syntax.
The parser allows more combinations than supported by the target CPU.
This inspection does a strict verification on the allowed addressing modes
and operation size for each assembly mnemonic.
<!-- tooltip end -->
<p>Several different error messages may be the result of this verification,
giving hints whether the first or the second addressing mode is unsupported,
or if the operands should be swapped to make it a legal instruction.
</p>
</body>
</html>
@@ -0,0 +1,20 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.codeInsight.documentation.DocumentationManager
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(LightCodeInsightExtension::class)
@TestDataPath("src/test/resources/documentation")
abstract class AbstractDocumentationProviderTest : AbstractM68kTest() {
fun generateDocumentation(myFixture: CodeInsightTestFixture): String? {
val docElement = DocumentationManager.getInstance(myFixture.project).findTargetElement(myFixture.editor, myFixture.file)
val provider = DocumentationManager.getProviderFromElement(docElement)
return provider.generateDoc(docElement, myFixture.file.findElementAt(myFixture.caretOffset))
}
}
@@ -0,0 +1,83 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.MyFixture
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(LightCodeInsightExtension::class)
internal class M68kInstructionDocumentationProviderTest : AbstractDocumentationProviderTest() {
@Test
internal fun check_documentation_inside_mnemonic(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"documentme.asm", """
mo<caret>veq.l #40,d0
"""
)
assertThat(generateDocumentation(myFixture)).isEqualToIgnoringWhitespace(
"""
<div class="definition"><pre><b>Move Quick</b></pre></div><div class="content"><table class="sections"><tr><td class="section" valign="top">Mnemonic</td><td class="section" valign="top">Op1</td><td class="section" valign="top">Op2</td></tr><tr><td valign="top"><div>moveq.l</div></td><td valign="top"><div>#&lt;xxx&gt;</div></td><td valign="top"><div>Dn</div></td></tr></table></div>
"""
)
}
@Test
internal fun check_documentation_inside_op_size(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"documentme.asm", """
bra.<caret>s label
"""
)
assertThat(generateDocumentation(myFixture)).isEqualToIgnoringWhitespace(
"""
<div class="definition">
<pre><b>Branch</b></pre>
</div>
<div class="content">
<table class="sections">
<tr>
<td class="section" valign="top">Mnemonic</td>
<td class="section" valign="top">Op1</td>
<td class="section" valign="top">Op2</td>
</tr>
<tr>
<td valign="top">
<div>bra.s</div>
<div>bra.b</div>
<div>bra.w</div>
</td>
<td valign="top">
<div>(xxx).w|l</div>
</td>
<td valign="top"></td>
</tr>
</table>
</div>
"""
)
}
@Test
internal fun check_documentation_for_privileged_instruction(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"documentme.asm", """
<caret>reset
"""
)
assertThat(generateDocumentation(myFixture)).contains("Reset External Devices", "(privileged)")
}
@Test
internal fun check_documentation_if_there_is_no_concrete_match(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"documentme.asm", """
<caret>cmp
"""
)
assertThat(generateDocumentation(myFixture))
.contains("<b>Compare</b>", "<b>Compare Address</b>", "<b>Compare Immediate</b>", "<b>Compare Memory to Memory</b>")
}
}
@@ -0,0 +1,102 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.MyFixture
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(LightCodeInsightExtension::class)
internal class M68kRegisterFlowDocumentationProviderTest : AbstractDocumentationProviderTest() {
@Test
internal fun check_documentation_for_a_register_in_code_flow(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"documentme.asm", """
label
moveq.l #0,d0
add.w #1,d0
move.l d1,-(sp)
move.w d0,d1
move.b d2,d0
addq.b #1,d0
move.w d<caret>0,d1
move.l d0,d2
move.w d1,d2
clr.b d0
moveq.l #0,d0
move.l (sp)+,d1
rts
nextlabel
"""
)
assertThat(generateDocumentation(myFixture))
.isEqualToIgnoringWhitespace(
"""
<div class="definition">move instruction reads d0.w</div>
<table class="sections" style="padding-left: 8pt; padding-right: 8pt">
<tr>
<td valign="top">        </td>
<td valign="top"><code>moveq.l #0,<font color="#ffc800">d0</font></code></td>
<td valign="top"> ; <font color="#00ff00">sets d0.l</font></td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>add.w #1,<font color="#ffc800">d0</font></code></td>
<td valign="top"> ; modifies d0.w</td>
</tr>
<tr>
<td valign="top">&nbsp;</td>
<td valign="top">
<div class="grayed">[...]</div>
</td>
<td valign="top">&nbsp;</td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>move.w <font color="#ffc800">d0</font>,d1</code></td>
<td valign="top"> ; reads d0.w</td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>move.b d2,<font color="#ffc800">d0</font></code></td>
<td valign="top"> ; <font color="#00ff00">sets d0.b</font></td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>addq.b #1,<font color="#ffc800">d0</font></code></td>
<td valign="top"> ; modifies d0.b</td>
</tr>
<tr>
<td valign="top">--&gt;</td>
<td valign="top"><b><code>move.w <font color="#ffc800">d0</font>,d1</code></b></td>
<td valign="top"> ; &lt;--</td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>move.l <font color="#ffc800">d0</font>,d2</code></td>
<td valign="top"> ; reads d0.l</td>
</tr>
<tr>
<td valign="top">&nbsp;</td>
<td valign="top">
<div class="grayed">[...]</div>
</td>
<td valign="top">&nbsp;</td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>clr.b <font color="#ffc800">d0</font></code></td>
<td valign="top"> ; <font color="#00ff00">sets d0.b</font></td>
</tr>
<tr>
<td valign="top">        </td>
<td valign="top"><code>moveq.l #0,<font color="#ffc800">d0</font></code></td>
<td valign="top"> ; <font color="#00ff00">sets d0.l</font></td>
</tr>
</table>
""".trimIndent()
)
}
}
@@ -0,0 +1,24 @@
package de.platon42.intellij.plugins.m68k.documentation
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.MyFixture
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(LightCodeInsightExtension::class)
internal class M68kSymbolDefinitionDocumentationProviderTest : AbstractDocumentationProviderTest() {
@Test
internal fun check_documentation_for_a_symbol_definition(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"documentme.asm", """
PIC_WIDTH = 320
move.w #PIC_WIDT<caret>H,d0
"""
)
assertThat(generateDocumentation(myFixture))
.isEqualTo("<div class='definition'><pre>PIC_WIDTH</pre></div><div class='content'>320</div>")
}
}
@@ -0,0 +1,18 @@
package de.platon42.intellij.plugins.m68k.inspections
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Condition
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(LightCodeInsightExtension::class)
@TestDataPath("src/test/resources/inspections")
abstract class AbstractInspectionTest : AbstractM68kTest() {
protected fun assertHighlightings(myFixture: CodeInsightTestFixture, count: Int, snippet: String) {
assertThat(myFixture.doHighlighting())
.areExactly(count, Condition({ it.description?.contains(snippet) ?: false }, "containing"))
}
}
@@ -0,0 +1,121 @@
package de.platon42.intellij.plugins.m68k.inspections
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.MyFixture
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
internal class M68kSyntaxInspectionTest : AbstractInspectionTest() {
@Test
internal fun shows_error_on_instruction_with_unexpected_operands(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " rts d0")
assertHighlightings(myFixture, 1, "No operands expected for 'rts'")
}
@Test
internal fun shows_error_on_instruction_with_unexpected_second_operand(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " jmp label,d0")
assertHighlightings(myFixture, 1, "Second operand 'd0' unexpected")
}
@Test
internal fun shows_unsupported_addressing_mode_in_first_operand(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " moveq.l 123,d0")
assertHighlightings(myFixture, 1, "Unsupported addressing mode '123' for first operand")
}
@Test
internal fun shows_unsupported_addressing_mode_in_second_operand(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " moveq.l #123,a0")
assertHighlightings(myFixture, 1, "Unsupported addressing mode 'a0' for second operand")
}
@Test
internal fun shows_unsupported_swapped_addressing_mode(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " cmp.l d0,(a0)")
assertHighlightings(myFixture, 1, "Unsupported addressing modes for operands in this order for 'cmp.l'")
}
@Test
internal fun shows_error_on_unsized_instruction_with_size(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " rts.l")
assertHighlightings(myFixture, 1, "Instruction 'rts' is unsized")
}
@Test
internal fun shows_error_for_bchg_on_unsupported_op_size_l(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " bchg.l #5,(a0)")
assertHighlightings(myFixture, 1, "Operation size '.l' unsupported (should be .b)")
}
@Test
internal fun shows_error_for_bchg_on_unsupported_op_size_b(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " bchg.b #5,d0")
assertHighlightings(myFixture, 1, "Operation size '.b' unsupported (should be .l)")
}
@Test
internal fun shows_error_for_bchg_on_unsupported_op_size_w(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " bchg.w #5,d0")
assertHighlightings(myFixture, 1, "Operation size '.w' unsupported (should be .l)")
}
@Test
internal fun does_not_show_error_for_bchg_without_size(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " bchg #5,d0")
assertThat(myFixture.doHighlighting()).isEmpty()
}
@Test
internal fun shows_error_on_unsupported_op_size_for_w(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " divu.b #5,d0")
assertHighlightings(myFixture, 1, "Operation size '.b' unsupported (should be .w)")
}
@Test
internal fun shows_error_on_unsupported_op_size_for_l(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " moveq.w #5,d0")
assertHighlightings(myFixture, 1, "Operation size '.w' unsupported (should be .l)")
}
@Test
internal fun shows_error_on_unsupported_op_size_for_w_or_l(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " addq.b #5,a0")
assertHighlightings(myFixture, 1, "Operation size '.b' unsupported (should be .w|.l)")
}
@Test
internal fun shows_error_on_unsupported_op_size_for_other(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " bsr.l label")
assertHighlightings(myFixture, 1, "Operation size '.l' unsupported")
}
@Test
internal fun shows_error_wrong_mode_on_instruction_with_special_reg(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " move.l usp,d0")
assertHighlightings(myFixture, 1, "Unsupported addressing mode for 'move.l'")
}
@Test
internal fun shows_error_wrong_register_on_instruction_with_special_reg(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.enableInspections(M68kSyntaxInspection::class.java)
myFixture.configureByText("syntax.asm", " move.l vbr,a0")
assertHighlightings(myFixture, 1, "Unsupported addressing mode for 'move.l'")
}
}
@@ -1,8 +1,12 @@
package de.platon42.intellij.plugins.m68k.parser
import com.intellij.psi.util.PsiTreeUtil
import de.platon42.intellij.jupiter.MyTestCase
import de.platon42.intellij.jupiter.ParsingTestExtension
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.asm.Register
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterListAddressingMode
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
@TestDataSubPath("addressingmodes")
@@ -85,7 +89,24 @@ internal class AddressingModesTest : AbstractParsingTest() {
@Test
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0-a2/a4,-(sp)\n")
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n")
val element = testCase.file.findElementAt(9)
val regList = PsiTreeUtil.getParentOfType(element, M68kRegisterListAddressingMode::class.java)!!
assertThat(regList.registers).containsExactlyInAnyOrder(
Register.D0, Register.D1, Register.D2, Register.D4,
Register.A0, Register.A2, Register.A3, Register.A5,
)
}
@Test
internal fun movem_register_list_with_data_address_wrapping(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, " movem.l d0-a6,-(sp)\n")
val element = testCase.file.findElementAt(9)
val regList = PsiTreeUtil.getParentOfType(element, M68kRegisterListAddressingMode::class.java)!!
assertThat(regList.registers).containsExactlyInAnyOrder(
Register.D0, Register.D1, Register.D2, Register.D3, Register.D4, Register.D5, Register.D6, Register.D7,
Register.A0, Register.A1, Register.A2, Register.A3, Register.A4, Register.A5, Register.A6,
)
}
@Test
@@ -95,12 +116,17 @@ internal class AddressingModesTest : AbstractParsingTest() {
@Test
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, " move.l usp,a0\n"
+ " move.l a5,usp\n")
testGoodSyntax(
testCase, " move.l usp,a0\n"
+ " move.l a5,usp\n"
)
}
@Test
internal fun complex_math_expression_in_displacement(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, " move.l -(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&$1f)(a0),(-(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&\$1f),a0,d0.l)\n")
testGoodSyntax(
testCase,
" move.l -(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&$1f)(a0),(-(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&\$1f),a0,d0.l)\n"
)
}
}
@@ -48,6 +48,11 @@ internal class ExpressionsTest : AbstractParsingTest() {
testGoodSyntax(testCase, " dc.w *-.label\n")
}
@Test
internal fun uppercase_hexadecimal_string(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, " move.l #\$DEADBEEF,d0\n")
}
@Test
internal fun if_with_single_equals_comparison(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, " IF DEBUG=1\n")
@@ -23,6 +23,11 @@ internal class MacroCallTest : AbstractParsingTest() {
testGoodSyntax(testCase, " PUSHM d0/d3/d5-d7/a0-a2/a4-a6 ; save a couple of registers\n")
}
@Test
internal fun call_with_label(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(testCase, "label FOOBAR narf ; wut?\n")
}
@Test
internal fun putmsg_call_with_specially_bracketed_parameters(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
// FIXME this doesn't work as intended...
@@ -0,0 +1,77 @@
package de.platon42.intellij.plugins.m68k.parser
import de.platon42.intellij.jupiter.MyTestCase
import de.platon42.intellij.jupiter.ParsingTestExtension
import de.platon42.intellij.jupiter.TestDataSubPath
import org.junit.jupiter.api.Test
@TestDataSubPath("macros")
internal class MacroDefinitionTest : AbstractParsingTest() {
@Test
internal fun macro_with_name_left(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
FOOBAR MACRO ; start of macro
.loop\@ move.l \1,(\2)+ ; just copy all the stuff
dbra \3,.loop\@
ENDM ; end of macro
move.w d0,d1
"""
)
}
@Test
internal fun macro_with_name_right(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
MACRO FOOBAR ; start of macro
.loop\@ move.l \1,(\2)+ ; just copy all the stuff
dbra \3,.loop\@
ENDM ; end of macro
label: move.w d0,d1
"""
)
}
@Test
internal fun empty_macro(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
MACRO FOOBAR
ENDM
NARF = 100
"""
)
}
@Test
internal fun two_macro_definitions_in_succession(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
MACRO FOOBAR1
.loop\@ move.l \1,(\2)+
dbra \3,.loop\@
ENDM
MACRO FOOBAR2
.loop\@ move.w \1,(\2)+
dbra \3,.loop\@
ENDM
label: move.w d0,d1
"""
)
}
@Test
internal fun macro_name_with_colon_p61_source_suxxor(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
testGoodSyntax(
testCase, """
structure:macro
\1:equ 0
soffset:set \2
endm"""
)
}
}
@@ -0,0 +1,32 @@
package de.platon42.intellij.plugins.m68k.refs
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
import de.platon42.intellij.jupiter.LightCodeInsightExtension
import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@TestDataPath("src/test/resources/references")
@TestDataSubPath("completion")
@ExtendWith(LightCodeInsightExtension::class)
internal class M68kMacroCallCompletionContributorTest : AbstractM68kTest() {
@Test
internal fun completion_shows_mnemonics_and_macros(@MyFixture myFixture: CodeInsightTestFixture) {
myFixture.configureByText(
"completeme.asm", """
noppy MACRO
ENDM
no<caret>
"""
)
myFixture.completeBasic()
assertThat(myFixture.lookupElementStrings).containsExactlyInAnyOrder("nop", "not", "noppy")
}
}
@@ -8,10 +8,7 @@ import de.platon42.intellij.jupiter.MyFixture
import de.platon42.intellij.jupiter.TestDataPath
import de.platon42.intellij.jupiter.TestDataSubPath
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
import de.platon42.intellij.plugins.m68k.psi.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@@ -71,4 +68,22 @@ internal class M68kReferenceContributorTest : AbstractM68kTest() {
myFixture.checkResultByFile("symbol_assignment_after_rename.asm")
}
@Test
@TestDataSubPath("macros")
internal fun reference_to_macro_can_be_renamed(@MyFixture myFixture: CodeInsightTestFixture) {
val file = myFixture.configureByFile("macros.asm")
val elementAtCaret = myFixture.elementAtCaret
assertThat(elementAtCaret).isInstanceOf(M68kMacroDefinition::class.java)
val macroDef = elementAtCaret as M68kMacroDefinition
assertThat(macroDef.macroNameDefinition.text).isEqualTo("PUTMSG")
myFixture.renameElementAtCaret("PRINTF")
val reference = file.findReferenceAt(myFixture.editor.caretModel.offset)!!
assertThat(reference).isInstanceOf(M68kMacroReference::class.java)
assertThat(reference.variants).isEmpty()
myFixture.checkResultByFile("macros_after_rename.asm")
}
}

Some files were not shown because too many files have changed in this diff Show More