Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
954f42bf63 | ||
|
|
94001c8b87 | ||
|
|
55403f89a6 | ||
|
|
7744b589d4 | ||
|
|
19e3b519db | ||
|
|
587b284d25 | ||
|
|
719460ebfe | ||
|
|
44a4721d77 | ||
|
|
09a4e62c7c | ||
|
|
ce3cdbbed6 | ||
|
|
27b7593de8 | ||
|
|
3aeb415974 | ||
|
|
128330d2c7 | ||
|
|
ef900e9c19 | ||
|
|
8ea70f0dfa | ||
|
|
fa1ef0b3d5 | ||
|
|
3de9e9eba2 | ||
|
|
25450a9bf8 | ||
|
|
6e683eb6a0 |
+13
@@ -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.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# MC68000 Assembly Language Plugin [](https://travis-ci.com/chrisly42/mc68000-asm-plugin) [](https://coveralls.io/github/chrisly42/mc68000-asm-plugin?branch=main)
|
# MC68000 Assembly Language Plugin [](https://travis-ci.com/chrisly42/mc68000-asm-plugin) [](https://coveralls.io/github/chrisly42/mc68000-asm-plugin?branch=main)
|
||||||
|
|
||||||
_MC68000 Assembly Language Plugin_ is plugin for Jetbrains IDEs (CLion, IntelliJ, etc.).
|
_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.
|
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.
|
it's "good enough" to get started, and I can return to demo coding with its current state.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
|
- 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!)
|
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
|
||||||
- Mnemonics code completion
|
- Mnemonics code completion
|
||||||
- Symbols / Labels code completion
|
- Symbols / Labels / Macros code completion
|
||||||
- References / Refactoring support for local and global labels, and symbol assignments.
|
- 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
|
- Brace matching
|
||||||
- Quote handler
|
- Quote handler
|
||||||
- Goto Symbol support
|
- Goto Symbol support
|
||||||
- Structure view
|
- Structure view
|
||||||
|
- Documentation provider for symbol definitions and mnemonics (listing available addressing modes etc.).
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
- No referencing of macro invocations and macro definitions.
|
- `Find Usages` always shows _"Unclassified"_ though it shouldn't (?)
|
||||||
- `Find Usages` always shows _"Unclassified"_ though it shouldn't.
|
|
||||||
- Macro definitions may cause syntax errors when using backslash arguments.
|
|
||||||
- Macro invocations are not yet evaluated, thus no referencing to symbols defined via macros (e.g. `STRUCT`).
|
- 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 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)
|
- 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 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).
|
- 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:
|
- Missing but planned features:
|
||||||
- Macro definition and evaluation on invocation
|
- Macro evaluation on invocation
|
||||||
- Folding
|
- Folding
|
||||||
- Semantic inspections
|
- Semantic inspections
|
||||||
- Quick fixes
|
- Quick fixes
|
||||||
- Formatter + Code Style Settings
|
- Formatter + Code Style Settings
|
||||||
- Register use analysis (but this only makes sense after macro evaluation)
|
- Register use analysis (but this only makes sense after macro evaluation)
|
||||||
|
- Cycle counting
|
||||||
|
|
||||||
## Recommendations
|
## Recommendations
|
||||||
|
|
||||||
@@ -69,11 +71,36 @@ make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.
|
|||||||
|
|
||||||
## Changelog
|
## 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)
|
### V0.2 (27-Jul-21)
|
||||||
|
|
||||||
- Cosmetics: Added (same) icon for plugin as for file type.
|
- 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: 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 Stub-Index for global labels and symbols.
|
||||||
- Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
|
- 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.
|
- Enhancement: Registers are now offered for code completion, making editing less annoying.
|
||||||
|
|
||||||
|
|||||||
+42
-10
@@ -7,7 +7,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = 'de.platon42'
|
group = 'de.platon42'
|
||||||
version = '0.2'
|
version = '0.4'
|
||||||
sourceCompatibility = "1.8"
|
sourceCompatibility = "1.8"
|
||||||
targetCompatibility = "1.8"
|
targetCompatibility = "1.8"
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ repositories {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
dependencies {
|
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.assertj:assertj-core:3.20.2"
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0-M1'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0-M1'
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
|
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
|
||||||
@@ -31,7 +31,10 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileKotlin {
|
compileKotlin {
|
||||||
kotlinOptions.jvmTarget = "1.8"
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
freeCompilerArgs += "-Xjvm-default=all"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTestKotlin {
|
compileTestKotlin {
|
||||||
@@ -39,25 +42,54 @@ compileTestKotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
intellij {
|
intellij {
|
||||||
setVersion("2021.1.3") // LATEST-EAP-SNAPSHOT
|
setVersion("2021.2") // LATEST-EAP-SNAPSHOT
|
||||||
setUpdateSinceUntilBuild(false)
|
setUpdateSinceUntilBuild(false)
|
||||||
// setPlugins(["com.intellij.java"])
|
// 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 {
|
patchPluginXml {
|
||||||
setChangeNotes("""
|
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>
|
<h4>V0.2 (27-Jul-21)</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Cosmetics: Added (same) icon for plugin as for file type.
|
<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: 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 Stub-Index for global labels and symbols.
|
||||||
<li>Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
|
<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.
|
<li>Enhancement: Registers are now offered for code completion, making editing less annoying.
|
||||||
</ul>
|
</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>
|
<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) {
|
public static boolean AddressRegisterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false;
|
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false;
|
||||||
if (!nextTokenIsFast(b, ROUND_L)) 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 && AddressRegisterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
||||||
r = r && AddressRegister(b, l + 1);
|
r = r && AddressRegister(b, l + 1);
|
||||||
r = r && consumeToken(b, SEPARATOR);
|
r = r && consumeToken(b, SEPARATOR);
|
||||||
r = r && DataOrAddressRegister(b, l + 1);
|
r = r && IndexRegister(b, l + 1);
|
||||||
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_5(b, l + 1);
|
|
||||||
r = r && consumeToken(b, ROUND_R);
|
r = r && consumeToken(b, ROUND_R);
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
@@ -246,15 +245,8 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return r;
|
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) {
|
public static boolean AddressRegisterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false;
|
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
@@ -263,8 +255,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
r = r && consumeToken(b, ROUND_L);
|
r = r && consumeToken(b, ROUND_L);
|
||||||
r = r && AddressRegister(b, l + 1);
|
r = r && AddressRegister(b, l + 1);
|
||||||
r = r && consumeToken(b, SEPARATOR);
|
r = r && consumeToken(b, SEPARATOR);
|
||||||
r = r && DataOrAddressRegister(b, l + 1);
|
r = r && IndexRegister(b, l + 1);
|
||||||
r = r && AddressRegisterIndirectWithIndexOldAddressingMode_5(b, l + 1);
|
|
||||||
r = r && consumeToken(b, ROUND_R);
|
r = r && consumeToken(b, ROUND_R);
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
@@ -277,13 +268,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return true;
|
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
|
// OPSIZE_W|OPSIZE_L
|
||||||
public static boolean AddressSize(PsiBuilder b, int l) {
|
public static boolean AddressSize(PsiBuilder b, int l) {
|
||||||
@@ -364,12 +348,12 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
// MNEMONIC OperandSize?
|
// MNEMONIC OperandSize?
|
||||||
public static boolean AsmOp(PsiBuilder b, int l) {
|
public static boolean AsmOp(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "AsmOp")) return false;
|
if (!recursion_guard_(b, l, "AsmOp")) return false;
|
||||||
if (!nextTokenIs(b, MNEMONIC)) return false;
|
if (!nextTokenIs(b, "<mnemonic>", MNEMONIC)) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
Marker m = enter_section_(b, l, _NONE_, ASM_OP, "<mnemonic>");
|
||||||
r = consumeToken(b, MNEMONIC);
|
r = consumeToken(b, MNEMONIC);
|
||||||
r = r && AsmOp_1(b, l + 1);
|
r = r && AsmOp_1(b, l + 1);
|
||||||
exit_section_(b, m, ASM_OP, r);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,11 +531,30 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return r;
|
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
|
// AsmInstruction | MacroCall
|
||||||
static boolean Instruction(PsiBuilder b, int l) {
|
static boolean Instruction(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "Instruction")) return false;
|
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;
|
boolean r;
|
||||||
r = AsmInstruction(b, l + 1);
|
r = AsmInstruction(b, l + 1);
|
||||||
if (!r) r = MacroCall(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) {
|
public static boolean MacroCall(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "MacroCall")) return false;
|
if (!recursion_guard_(b, l, "MacroCall")) return false;
|
||||||
if (!nextTokenIs(b, MACRO_INVOKATION)) return false;
|
if (!nextTokenIs(b, MACRO_INVOCATION)) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
Marker m = enter_section_(b);
|
||||||
r = consumeToken(b, MACRO_INVOKATION);
|
r = consumeToken(b, MACRO_INVOCATION);
|
||||||
r = r && MacroCall_1(b, l + 1);
|
r = r && MacroCall_1(b, l + 1);
|
||||||
exit_section_(b, m, MACRO_CALL, r);
|
exit_section_(b, m, MACRO_CALL, r);
|
||||||
return r;
|
return r;
|
||||||
@@ -657,6 +660,97 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return true;
|
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
|
// OPSIZE_BS|OPSIZE_W|OPSIZE_L
|
||||||
public static boolean OperandSize(PsiBuilder b, int 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) {
|
static boolean PlainOperands(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PlainOperands")) return false;
|
if (!recursion_guard_(b, l, "PlainOperands")) return false;
|
||||||
if (!nextTokenIs(b, STRINGLIT)) return false;
|
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
Marker m = enter_section_(b);
|
||||||
r = consumeToken(b, STRINGLIT);
|
r = PlainOperands_0(b, l + 1);
|
||||||
r = r && PlainOperands_1(b, l + 1);
|
r = r && PlainOperands_1(b, l + 1);
|
||||||
exit_section_(b, m, null, r);
|
exit_section_(b, m, null, r);
|
||||||
return 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) {
|
private static boolean PlainOperands_1(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PlainOperands_1")) return false;
|
if (!recursion_guard_(b, l, "PlainOperands_1")) return false;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -694,16 +796,26 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEPARATOR STRINGLIT
|
// SEPARATOR (expr|AddressingMode)
|
||||||
private static boolean PlainOperands_1_0(PsiBuilder b, int l) {
|
private static boolean PlainOperands_1_0(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "PlainOperands_1_0")) return false;
|
if (!recursion_guard_(b, l, "PlainOperands_1_0")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
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);
|
exit_section_(b, m, null, r);
|
||||||
return 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)
|
// Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
||||||
// PreprocessorOperands?
|
// 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) {
|
public static boolean ProgramCounterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false;
|
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false;
|
||||||
if (!nextTokenIsFast(b, ROUND_L)) 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 = consumeTokenFast(b, ROUND_L);
|
||||||
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
||||||
r = r && consumeTokens(b, 0, PC, SEPARATOR);
|
r = r && consumeTokens(b, 0, PC, SEPARATOR);
|
||||||
r = r && DataOrAddressRegister(b, l + 1);
|
r = r && IndexRegister(b, l + 1);
|
||||||
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_5(b, l + 1);
|
|
||||||
r = r && consumeToken(b, ROUND_R);
|
r = r && consumeToken(b, ROUND_R);
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
@@ -863,23 +974,15 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return r;
|
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) {
|
public static boolean ProgramCounterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false;
|
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>");
|
Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>");
|
||||||
r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1);
|
r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1);
|
||||||
r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR);
|
r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR);
|
||||||
r = r && DataOrAddressRegister(b, l + 1);
|
r = r && IndexRegister(b, l + 1);
|
||||||
r = r && ProgramCounterIndirectWithIndexOldAddressingMode_5(b, l + 1);
|
|
||||||
r = r && consumeToken(b, ROUND_R);
|
r = r && consumeToken(b, ROUND_R);
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
@@ -892,13 +995,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return true;
|
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
|
// CURRENT_PC_SYMBOL
|
||||||
public static boolean ProgramCounterReference(PsiBuilder b, int l) {
|
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) {
|
public static boolean RegisterListAddressingMode(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode")) return false;
|
if (!recursion_guard_(b, l, "RegisterListAddressingMode")) return false;
|
||||||
boolean r;
|
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 = RegisterListAddressingMode_0(b, l + 1);
|
||||||
r = r && RegisterListAddressingMode_1(b, l + 1);
|
r = r && RegisterListAddressingMode_1(b, l + 1);
|
||||||
exit_section_(b, l, m, r, false, null);
|
exit_section_(b, l, m, r, false, null);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataOrAddressRegister|RegisterRange
|
// RegisterRange|DataOrAddressRegister
|
||||||
private static boolean RegisterListAddressingMode_0(PsiBuilder b, int l) {
|
private static boolean RegisterListAddressingMode_0(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_0")) return false;
|
if (!recursion_guard_(b, l, "RegisterListAddressingMode_0")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
r = DataOrAddressRegister(b, l + 1);
|
r = RegisterRange(b, l + 1);
|
||||||
if (!r) r = RegisterRange(b, l + 1);
|
if (!r) r = DataOrAddressRegister(b, l + 1);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
|
// (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
|
||||||
private static boolean RegisterListAddressingMode_1(PsiBuilder b, int l) {
|
private static boolean RegisterListAddressingMode_1(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1")) return false;
|
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1")) return false;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -956,44 +1052,71 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange)
|
// OP_AR_DIV (RegisterRange|DataOrAddressRegister)
|
||||||
private static boolean RegisterListAddressingMode_1_0(PsiBuilder b, int l) {
|
private static boolean RegisterListAddressingMode_1_0(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0")) return false;
|
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
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);
|
r = r && RegisterListAddressingMode_1_0_1(b, l + 1);
|
||||||
exit_section_(b, m, null, r);
|
exit_section_(b, m, null, r);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OP_AR_DIV|OP_MINUS
|
// RegisterRange|DataOrAddressRegister
|
||||||
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
|
|
||||||
private static boolean RegisterListAddressingMode_1_0_1(PsiBuilder b, int l) {
|
private static boolean RegisterListAddressingMode_1_0_1(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0_1")) return false;
|
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0_1")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
r = DataOrAddressRegister(b, l + 1);
|
r = RegisterRange(b, l + 1);
|
||||||
if (!r) r = RegisterRange(b, l + 1);
|
if (!r) r = DataOrAddressRegister(b, l + 1);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ********************************************************** */
|
/* ********************************************************** */
|
||||||
// DataOrAddressRegister OP_MINUS DataOrAddressRegister
|
// (DataRegister OP_MINUS DataRegister) | (AddressRegister OP_MINUS AddressRegister) | (DataRegister OP_MINUS AddressRegister)
|
||||||
static boolean RegisterRange(PsiBuilder b, int l) {
|
public static boolean RegisterRange(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "RegisterRange")) return false;
|
if (!recursion_guard_(b, l, "RegisterRange")) return false;
|
||||||
boolean r;
|
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);
|
Marker m = enter_section_(b);
|
||||||
r = DataOrAddressRegister(b, l + 1);
|
r = DataRegister(b, l + 1);
|
||||||
r = r && consumeToken(b, OP_MINUS);
|
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);
|
exit_section_(b, m, null, r);
|
||||||
return 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) {
|
static boolean line(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "line")) return false;
|
if (!recursion_guard_(b, l, "line")) return false;
|
||||||
boolean r;
|
boolean r;
|
||||||
Marker m = enter_section_(b);
|
Marker m = enter_section_(b);
|
||||||
r = line_0(b, l + 1);
|
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);
|
r = r && line_2(b, l + 1);
|
||||||
exit_section_(b, m, null, r);
|
exit_section_(b, m, null, r);
|
||||||
return r;
|
return r;
|
||||||
@@ -1070,6 +1193,17 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
|||||||
return r;
|
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
|
// <<eof>>|EOL
|
||||||
private static boolean line_2(PsiBuilder b, int l) {
|
private static boolean line_2(PsiBuilder b, int l) {
|
||||||
if (!recursion_guard_(b, l, "line_2")) return false;
|
if (!recursion_guard_(b, l, "line_2")) return false;
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectPostIncAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectPostIncAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectPreDecAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectPreDecAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|||||||
+2
-2
@@ -3,12 +3,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,12 +3,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-6
@@ -4,18 +4,15 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement, M68kWithIndexRegister {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kDataWidth getDataWidth();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kRegister getRegister();
|
M68kIndexRegister getIndexRegister();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-6
@@ -4,18 +4,15 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M68kAddressingMode {
|
public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement, M68kWithIndexRegister {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kAddressRegister getAddressRegister();
|
M68kAddressRegister getAddressRegister();
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kDataWidth getDataWidth();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kRegister getRegister();
|
M68kIndexRegister getIndexRegister();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// This is a generated file. Not intended for manual editing.
|
// This is a generated file. Not intended for manual editing.
|
||||||
package de.platon42.intellij.plugins.m68k.psi;
|
package de.platon42.intellij.plugins.m68k.psi;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface M68kAsmOp extends M68kPsiElement {
|
public interface M68kAsmOp extends M68kPsiElement {
|
||||||
@@ -8,4 +9,9 @@ public interface M68kAsmOp extends M68kPsiElement {
|
|||||||
@Nullable
|
@Nullable
|
||||||
M68kOperandSize getOperandSize();
|
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.
|
// This is a generated file. Not intended for manual editing.
|
||||||
package de.platon42.intellij.plugins.m68k.psi;
|
package de.platon42.intellij.plugins.m68k.psi;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface M68kMacroCall extends M68kPsiElement {
|
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 {
|
public interface M68kOperandSize extends M68kPsiElement {
|
||||||
|
|
||||||
|
int getSize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface M68kProgramCounterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode {
|
public interface M68kProgramCounterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface M68kProgramCounterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode {
|
public interface M68kProgramCounterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-6
@@ -4,15 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode {
|
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kDataWidth getDataWidth();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kRegister getRegister();
|
M68kIndexRegister getIndexRegister();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-6
@@ -4,15 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode {
|
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
|
||||||
|
|
||||||
@Nullable
|
|
||||||
M68kDataWidth getDataWidth();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
M68kRegister getRegister();
|
M68kIndexRegister getIndexRegister();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
M68kExpr getExpr();
|
M68kExpr getDisplacement();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
// This is a generated file. Not intended for manual editing.
|
// This is a generated file. Not intended for manual editing.
|
||||||
package de.platon42.intellij.plugins.m68k.psi;
|
package de.platon42.intellij.plugins.m68k.psi;
|
||||||
|
|
||||||
|
import de.platon42.intellij.plugins.m68k.asm.Register;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface M68kRegisterListAddressingMode extends M68kAddressingMode {
|
public interface M68kRegisterListAddressingMode extends M68kAddressingMode {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
List<M68kRegister> getRegisterList();
|
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 EXPR = new M68kElementType("EXPR");
|
||||||
IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL");
|
IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL");
|
||||||
IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA");
|
IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA");
|
||||||
|
IElementType INDEX_REGISTER = new M68kElementType("INDEX_REGISTER");
|
||||||
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
|
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
|
||||||
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
|
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
|
||||||
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
|
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 OPERAND_SIZE = new M68kElementType("OPERAND_SIZE");
|
||||||
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
|
IElementType PAREN_EXPR = new M68kElementType("PAREN_EXPR");
|
||||||
IElementType PREPROCESSOR_DIRECTIVE = new M68kElementType("PREPROCESSOR_DIRECTIVE");
|
IElementType PREPROCESSOR_DIRECTIVE = new M68kElementType("PREPROCESSOR_DIRECTIVE");
|
||||||
@@ -62,6 +66,7 @@ public interface M68kTypes {
|
|||||||
IElementType REF_EXPR = new M68kElementType("REF_EXPR");
|
IElementType REF_EXPR = new M68kElementType("REF_EXPR");
|
||||||
IElementType REGISTER = new M68kElementType("REGISTER");
|
IElementType REGISTER = new M68kElementType("REGISTER");
|
||||||
IElementType REGISTER_LIST_ADDRESSING_MODE = new M68kElementType("REGISTER_LIST_ADDRESSING_MODE");
|
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 = new M68kElementType("SPECIAL_REGISTER");
|
||||||
IElementType SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE = new M68kElementType("SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE");
|
IElementType SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE = new M68kElementType("SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE");
|
||||||
IElementType STATEMENT = new M68kElementType("STATEMENT");
|
IElementType STATEMENT = new M68kElementType("STATEMENT");
|
||||||
@@ -86,7 +91,11 @@ public interface M68kTypes {
|
|||||||
IElementType HASH = new M68kTokenType("HASH");
|
IElementType HASH = new M68kTokenType("HASH");
|
||||||
IElementType HEXADECIMAL = new M68kTokenType("HEXADECIMAL");
|
IElementType HEXADECIMAL = new M68kTokenType("HEXADECIMAL");
|
||||||
IElementType LOCAL_LABEL_DEF = new M68kTokenType("LOCAL_LABEL_DEF");
|
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 MNEMONIC = new M68kTokenType("MNEMONIC");
|
||||||
IElementType OCTAL = new M68kTokenType("OCTAL");
|
IElementType OCTAL = new M68kTokenType("OCTAL");
|
||||||
IElementType OPSIZE_BS = new M68kTokenType("OPSIZE_BS");
|
IElementType OPSIZE_BS = new M68kTokenType("OPSIZE_BS");
|
||||||
@@ -204,12 +213,20 @@ public interface M68kTypes {
|
|||||||
return new M68kGlobalLabelImpl(node);
|
return new M68kGlobalLabelImpl(node);
|
||||||
} else if (type == IMMEDIATE_DATA) {
|
} else if (type == IMMEDIATE_DATA) {
|
||||||
return new M68kImmediateDataImpl(node);
|
return new M68kImmediateDataImpl(node);
|
||||||
|
} else if (type == INDEX_REGISTER) {
|
||||||
|
return new M68kIndexRegisterImpl(node);
|
||||||
} else if (type == LITERAL_EXPR) {
|
} else if (type == LITERAL_EXPR) {
|
||||||
return new M68kLiteralExprImpl(node);
|
return new M68kLiteralExprImpl(node);
|
||||||
} else if (type == LOCAL_LABEL) {
|
} else if (type == LOCAL_LABEL) {
|
||||||
return new M68kLocalLabelImpl(node);
|
return new M68kLocalLabelImpl(node);
|
||||||
} else if (type == MACRO_CALL) {
|
} else if (type == MACRO_CALL) {
|
||||||
return new M68kMacroCallImpl(node);
|
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) {
|
} else if (type == OPERAND_SIZE) {
|
||||||
return new M68kOperandSizeImpl(node);
|
return new M68kOperandSizeImpl(node);
|
||||||
} else if (type == PAREN_EXPR) {
|
} else if (type == PAREN_EXPR) {
|
||||||
@@ -230,6 +247,8 @@ public interface M68kTypes {
|
|||||||
return new M68kRefExprImpl(node);
|
return new M68kRefExprImpl(node);
|
||||||
} else if (type == REGISTER_LIST_ADDRESSING_MODE) {
|
} else if (type == REGISTER_LIST_ADDRESSING_MODE) {
|
||||||
return new M68kRegisterListAddressingModeImpl(node);
|
return new M68kRegisterListAddressingModeImpl(node);
|
||||||
|
} else if (type == REGISTER_RANGE) {
|
||||||
|
return new M68kRegisterRangeImpl(node);
|
||||||
} else if (type == SPECIAL_REGISTER) {
|
} else if (type == SPECIAL_REGISTER) {
|
||||||
return new M68kSpecialRegisterImpl(node);
|
return new M68kSpecialRegisterImpl(node);
|
||||||
} else if (type == SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE) {
|
} else if (type == SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE) {
|
||||||
|
|||||||
@@ -20,30 +20,43 @@ public class M68kVisitor extends PsiElementVisitor {
|
|||||||
|
|
||||||
public void visitAddressRegisterIndirectAddressingMode(@NotNull M68kAddressRegisterIndirectAddressingMode o) {
|
public void visitAddressRegisterIndirectAddressingMode(@NotNull M68kAddressRegisterIndirectAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressRegisterIndirectPostIncAddressingMode(@NotNull M68kAddressRegisterIndirectPostIncAddressingMode o) {
|
public void visitAddressRegisterIndirectPostIncAddressingMode(@NotNull M68kAddressRegisterIndirectPostIncAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressRegisterIndirectPreDecAddressingMode(@NotNull M68kAddressRegisterIndirectPreDecAddressingMode o) {
|
public void visitAddressRegisterIndirectPreDecAddressingMode(@NotNull M68kAddressRegisterIndirectPreDecAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressRegisterIndirectWithDisplacementNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementNewAddressingMode o) {
|
public void visitAddressRegisterIndirectWithDisplacementNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementNewAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressRegisterIndirectWithDisplacementOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementOldAddressingMode o) {
|
public void visitAddressRegisterIndirectWithDisplacementOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementOldAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressRegisterIndirectWithIndexNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexNewAddressingMode o) {
|
public void visitAddressRegisterIndirectWithIndexNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexNewAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
|
// visitWithIndexRegister(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressRegisterIndirectWithIndexOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexOldAddressingMode o) {
|
public void visitAddressRegisterIndirectWithIndexOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexOldAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithAddressRegisterIndirect(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
|
// visitWithIndexRegister(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitAddressSize(@NotNull M68kAddressSize o) {
|
public void visitAddressSize(@NotNull M68kAddressSize o) {
|
||||||
@@ -86,6 +99,10 @@ public class M68kVisitor extends PsiElementVisitor {
|
|||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitIndexRegister(@NotNull M68kIndexRegister o) {
|
||||||
|
visitPsiElement(o);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitLocalLabel(@NotNull M68kLocalLabel o) {
|
public void visitLocalLabel(@NotNull M68kLocalLabel o) {
|
||||||
visitNamedElement(o);
|
visitNamedElement(o);
|
||||||
}
|
}
|
||||||
@@ -94,6 +111,18 @@ public class M68kVisitor extends PsiElementVisitor {
|
|||||||
visitPsiElement(o);
|
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) {
|
public void visitOperandSize(@NotNull M68kOperandSize o) {
|
||||||
visitPsiElement(o);
|
visitPsiElement(o);
|
||||||
}
|
}
|
||||||
@@ -104,18 +133,24 @@ public class M68kVisitor extends PsiElementVisitor {
|
|||||||
|
|
||||||
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
|
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitProgramCounterIndirectWithDisplacementOldAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementOldAddressingMode o) {
|
public void visitProgramCounterIndirectWithDisplacementOldAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementOldAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitProgramCounterIndirectWithIndexNewAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexNewAddressingMode o) {
|
public void visitProgramCounterIndirectWithIndexNewAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexNewAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
|
// visitWithIndexRegister(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitProgramCounterIndirectWithIndexOldAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexOldAddressingMode o) {
|
public void visitProgramCounterIndirectWithIndexOldAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexOldAddressingMode o) {
|
||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
|
// visitWithDisplacement(o);
|
||||||
|
// visitWithIndexRegister(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitProgramCounterReference(@NotNull M68kProgramCounterReference o) {
|
public void visitProgramCounterReference(@NotNull M68kProgramCounterReference o) {
|
||||||
@@ -130,6 +165,10 @@ public class M68kVisitor extends PsiElementVisitor {
|
|||||||
visitAddressingMode(o);
|
visitAddressingMode(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitRegisterRange(@NotNull M68kRegisterRange o) {
|
||||||
|
visitPsiElement(o);
|
||||||
|
}
|
||||||
|
|
||||||
public void visitSpecialRegister(@NotNull M68kSpecialRegister o) {
|
public void visitSpecialRegister(@NotNull M68kSpecialRegister o) {
|
||||||
visitRegister(o);
|
visitRegister(o);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ public class M68kAddressRegisterIndirectWithDisplacementNewAddressingModeImpl ex
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ public class M68kAddressRegisterIndirectWithDisplacementOldAddressingModeImpl ex
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-9
@@ -31,21 +31,15 @@ public class M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl extends M
|
|||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kDataWidth getDataWidth() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kRegister getRegister() {
|
public M68kIndexRegister getIndexRegister() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-9
@@ -31,21 +31,15 @@ public class M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl extends M
|
|||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kDataWidth getDataWidth() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kRegister getRegister() {
|
public M68kIndexRegister getIndexRegister() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.intellij.psi.PsiElementVisitor;
|
|||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp;
|
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize;
|
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 de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -33,4 +34,15 @@ public class M68kAsmOpImpl extends ASTWrapperPsiElement implements M68kAsmOp {
|
|||||||
return PsiTreeUtil.getChildOfType(this, M68kOperandSize.class);
|
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.
|
// This is a generated file. Not intended for manual editing.
|
||||||
package de.platon42.intellij.plugins.m68k.psi.impl;
|
package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||||
|
|
||||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElementVisitor;
|
import com.intellij.psi.PsiElementVisitor;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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) {
|
public M68kMacroCallImpl(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
@@ -24,4 +25,22 @@ public class M68kMacroCallImpl extends ASTWrapperPsiElement implements M68kMacro
|
|||||||
else super.accept(visitor);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+27
@@ -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.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElementVisitor;
|
import com.intellij.psi.PsiElementVisitor;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize;
|
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 de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -24,4 +25,9 @@ public class M68kOperandSizeImpl extends ASTWrapperPsiElement implements M68kOpe
|
|||||||
else super.accept(visitor);
|
else super.accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSize() {
|
||||||
|
return M68kPsiImplUtil.getSize(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ public class M68kProgramCounterIndirectWithDisplacementNewAddressingModeImpl ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ public class M68kProgramCounterIndirectWithDisplacementOldAddressingModeImpl ext
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-10
@@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
|||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElementVisitor;
|
import com.intellij.psi.PsiElementVisitor;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -25,21 +28,15 @@ public class M68kProgramCounterIndirectWithIndexNewAddressingModeImpl extends M6
|
|||||||
else super.accept(visitor);
|
else super.accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kDataWidth getDataWidth() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kRegister getRegister() {
|
public M68kIndexRegister getIndexRegister() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-10
@@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
|||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElementVisitor;
|
import com.intellij.psi.PsiElementVisitor;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -25,21 +28,15 @@ public class M68kProgramCounterIndirectWithIndexOldAddressingModeImpl extends M6
|
|||||||
else super.accept(visitor);
|
else super.accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
public M68kDataWidth getDataWidth() {
|
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public M68kRegister getRegister() {
|
public M68kIndexRegister getIndexRegister() {
|
||||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public M68kExpr getExpr() {
|
public M68kExpr getDisplacement() {
|
||||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-3
@@ -4,12 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
|||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElementVisitor;
|
import com.intellij.psi.PsiElementVisitor;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegister;
|
import de.platon42.intellij.plugins.m68k.asm.Register;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterListAddressingMode;
|
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl implements M68kRegisterListAddressingMode {
|
public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl implements M68kRegisterListAddressingMode {
|
||||||
|
|
||||||
@@ -34,4 +34,16 @@ public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl i
|
|||||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegister.class);
|
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
|
@JvmField
|
||||||
val INSTANCE = M68kFileElementType()
|
val INSTANCE = M68kFileElementType()
|
||||||
|
|
||||||
const val STUB_VERSION = 3
|
const val STUB_VERSION = 5
|
||||||
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
|
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
|
||||||
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
|
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 FILE = IconLoader.getIcon("/icons/FileType_m68k.svg", javaClass)
|
||||||
val LOCAL_LABEL = AllIcons.Nodes.AbstractMethod
|
val LOCAL_LABEL = AllIcons.Nodes.AbstractMethod
|
||||||
val GLOBAL_LABEL = AllIcons.Nodes.Method
|
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 {
|
object AssemblerDirectives {
|
||||||
|
|
||||||
val dataDirectives: Set<String> = setOf(
|
val dataDirectives: Set<String> = setOf(
|
||||||
"section", "pushsection", "popsection",
|
"section", "pushsection", "popsection",
|
||||||
"bss", "bss_c", "bss_f",
|
"bss", "bss_c", "bss_f",
|
||||||
"data", "data_c", "data_f",
|
"data", "data_c", "data_f",
|
||||||
"text", "cseg", "code", "code_c", "code_f",
|
"text", "cseg", "code", "code_c", "code_f",
|
||||||
"offset",
|
"offset",
|
||||||
|
|
||||||
"abs",
|
"abs",
|
||||||
"db", "dw", "dl",
|
"db", "dw", "dl",
|
||||||
"dr.b", "dr.w", "dr.l",
|
"dr.b", "dr.w", "dr.l",
|
||||||
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
|
"dc", "dc.b", "dc.w", "dc.l", "dcb", "dcb.b", "dcb.w", "dcb.l",
|
||||||
"blk.b", "blk.w", "blk.l",
|
"blk.b", "blk.w", "blk.l",
|
||||||
"ds", "ds.b", "ds.w", "ds.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",
|
"cargs", "comm", "comment",
|
||||||
"rsset", "clrfo", "clrso", "setfo", "setso"
|
"rsset", "clrfo", "clrso", "setfo", "setso"
|
||||||
)
|
)
|
||||||
|
|
||||||
val otherDirective: Set<String> = setOf(
|
val otherDirective: Set<String> = setOf(
|
||||||
"if",
|
"if",
|
||||||
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
|
"ifeq", "ifne", "ifgt", "ifge", "iflt", "ifle", "ifb", "ifnb", "ifc", "ifnc",
|
||||||
"ifd", "ifnd", "ifmacrod", "ifmacrond",
|
"ifd", "ifnd", "ifmacrod", "ifmacrond",
|
||||||
//"iif" // not supported
|
//"iif" // not supported
|
||||||
"else", "endif", "endc",
|
"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",
|
"incdir", "include", "incbin", "output",
|
||||||
"org",
|
|
||||||
|
|
||||||
"assert", "fail", "print", "printt", "printv", "echo",
|
"list", "nlist", "nolist", "llen", "nopage", "page", "spc",
|
||||||
|
"org",
|
||||||
|
|
||||||
"inline", "einline",
|
"assert", "fail", "print", "printt", "printv", "echo",
|
||||||
"rem", "erem"
|
|
||||||
|
"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
|
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(
|
data class IsaData(
|
||||||
val mnemonic: String,
|
val mnemonic: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
@@ -16,141 +128,602 @@ data class IsaData(
|
|||||||
val altMnemonics: List<String> = emptyList(),
|
val altMnemonics: List<String> = emptyList(),
|
||||||
val conditionCodes: List<String> = emptyList(),
|
val conditionCodes: List<String> = emptyList(),
|
||||||
val id: String = mnemonic,
|
val id: String = mnemonic,
|
||||||
val opSize: String = "bWl",
|
|
||||||
val isPrivileged: Boolean = false,
|
val isPrivileged: Boolean = false,
|
||||||
val hasOps: Boolean = true
|
val hasOps: Boolean = true,
|
||||||
|
val modes: List<AllowedAdrMode> = listOf(AllowedAdrMode()),
|
||||||
)
|
)
|
||||||
|
|
||||||
object M68kIsa {
|
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
|
// Data Movement Instructions
|
||||||
IsaData("move", "Move"),
|
IsaData(
|
||||||
IsaData("movea", "Move Address", altMnemonics = listOf("move"), opSize = "L"),
|
"move", "Move",
|
||||||
IsaData("movem", "Move Multiple Registers", opSize = "Wl"),
|
modes = listOf(AllowedAdrMode(ALL_68000_MODES, ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, modInfo = RWM_READ_OP1_OPSIZE or RWM_SET_OP2_OPSIZE))
|
||||||
IsaData("movep", "Move Peripheral", opSize = ""),
|
),
|
||||||
IsaData("moveq", "Move Quick", opSize = "L"),
|
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(
|
||||||
IsaData("lea", "Load Effective Address", opSize = ""),
|
"moveq", "Move Quick",
|
||||||
IsaData("pea", "Push Effective Address", opSize = ""),
|
modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_SET_OP2_L))
|
||||||
IsaData("link", "Link and Allocate", opSize = ""),
|
),
|
||||||
IsaData("unlk", "Unlink", opSize = ""),
|
|
||||||
|
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
|
// Integer Arithmetic Instructions
|
||||||
IsaData("add", "Add"),
|
IsaData("add", "Add", modes = ADD_SUB_MODES),
|
||||||
IsaData("adda", "Add Address", altMnemonics = listOf("add"), opSize = "Wl"),
|
IsaData(
|
||||||
IsaData("addi", "Add Immediate", altMnemonics = listOf("add")),
|
"adda", "Add Address", altMnemonics = listOf("add"),
|
||||||
IsaData("addq", "Add Quick"),
|
modes = listOf(
|
||||||
IsaData("addx", "Add with Extend"),
|
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("sub", "Subtract", modes = ADD_SUB_MODES),
|
||||||
IsaData("suba", "Subtract Address", altMnemonics = listOf("sub")),
|
IsaData(
|
||||||
IsaData("subi", "Subtract Immediate", altMnemonics = listOf("sub")),
|
"suba", "Subtract Address", altMnemonics = listOf("sub"),
|
||||||
IsaData("subq", "Subtract Quick"),
|
modes = listOf(AllowedAdrMode(ALL_68000_MODES, AREG_ONLY, OP_SIZE_WL, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_L))
|
||||||
IsaData("subx", "Subtract with Extend"),
|
),
|
||||||
|
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("neg", "Negate", modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG_IMMEDIATE_AND_PC_REL, null, modInfo = RWM_MODIFY_OP1_OPSIZE))),
|
||||||
IsaData("negx", "Negate with Extend"),
|
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(
|
||||||
IsaData("cmpa", "Compare Address", altMnemonics = listOf("cmp"), opSize = "Wl"),
|
"cmp", "Compare", modes = listOf(
|
||||||
IsaData("cmpi", "Compare Immediate", altMnemonics = listOf("cmp")),
|
AllowedAdrMode(ALL_EXCEPT_AREG, setOf(AddressMode.DATA_REGISTER_DIRECT), modInfo = RWM_READ_OP1_OPSIZE or RWM_READ_OP2_OPSIZE),
|
||||||
IsaData("cmpm", "Compare Memory to Memory", altMnemonics = listOf("cmp")),
|
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(
|
||||||
IsaData("mulu", "Unsigned Multiply", opSize = "W"),
|
"muls", "Signed Multiply",
|
||||||
IsaData("divs", "Signed Divide", opSize = "W"),
|
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_W or RWM_MODIFY_OP2_L))
|
||||||
IsaData("divu", "Unsigned Divide", opSize = "W"),
|
),
|
||||||
|
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
|
// Logical Instructions
|
||||||
IsaData("and", "Logical AND"),
|
IsaData(
|
||||||
IsaData("andi", "Logical AND Immediate", altMnemonics = listOf("and")),
|
"and", "Logical AND",
|
||||||
IsaData("eor", "Logical Exclusive-OR"),
|
modes = listOf(
|
||||||
IsaData("eori", "Logical Exclusive-OR Immediate", altMnemonics = listOf("eor")),
|
AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE),
|
||||||
IsaData("not", "Logical Complement"),
|
AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE)
|
||||||
IsaData("or", "Logical Inclusive-OR"),
|
)
|
||||||
IsaData("ori", "Logical Inclusive-OR Immediate", altMnemonics = listOf("or")),
|
),
|
||||||
|
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
|
// Shift and Rotate Instructions
|
||||||
IsaData("asl", "Arithmetic Shift Left"),
|
IsaData("asl", "Arithmetic Shift Left", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("asr", "Arithmetic Shift Right"),
|
IsaData("asr", "Arithmetic Shift Right", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("lsl", "Logical Shift Left"),
|
IsaData("lsl", "Logical Shift Left", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("lsr", "Logical Shift Right"),
|
IsaData("lsr", "Logical Shift Right", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("rol", "Rotate Left"),
|
IsaData("rol", "Rotate Left", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("ror", "Rotate Right"),
|
IsaData("ror", "Rotate Right", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("roxl", "Rotate with Extend Left"),
|
IsaData("roxl", "Rotate with Extend Left", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("roxr", "Rotate with Extend Right"),
|
IsaData("roxr", "Rotate with Extend Right", modes = ASD_LSD_ROD_ROXD_MODES),
|
||||||
IsaData("swap", "Swap Register Words", opSize = ""),
|
IsaData("swap", "Swap Register Words", modes = listOf(AllowedAdrMode(DREG_ONLY, null, OP_SIZE_W, modInfo = RWM_MODIFY_OP1_L))),
|
||||||
|
|
||||||
// Bit Manipulation Instructions
|
// Bit Manipulation Instructions
|
||||||
IsaData("bchg", "Test Bit and Change", opSize = "Bl"),
|
IsaData("bchg", "Test Bit and Change", modes = BCHG_BCLR_BSET_MODES),
|
||||||
IsaData("bclr", "Test Bit and Clear", opSize = "Bl"),
|
IsaData("bclr", "Test Bit and Clear", modes = BCHG_BCLR_BSET_MODES),
|
||||||
IsaData("bset", "Test Bit and Set", opSize = "Bl"),
|
IsaData("bset", "Test Bit and Set", modes = BCHG_BCLR_BSET_MODES),
|
||||||
IsaData("btst", "Test Bit", opSize = "Bl"),
|
IsaData("btst", "Test Bit", modes = BTST_MODES),
|
||||||
|
|
||||||
// Binary-Coded Decimal Instructions
|
// Binary-Coded Decimal Instructions
|
||||||
IsaData("abcd", "Add Decimal with Extend", opSize = ""),
|
IsaData(
|
||||||
IsaData("sbcd", "Subtract Decimal with Extend", opSize = ""),
|
"abcd", "Add Decimal with Extend",
|
||||||
IsaData("nbcd", "Negate Decimal with Extend", opSize = ""),
|
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
|
// Program Control Instructions
|
||||||
IsaData("bCC", "Branch Conditionally", conditionCodes = conditionCodesBcc, opSize = "bsW"),
|
IsaData(
|
||||||
IsaData("bra", "Branch", opSize = "bsW"),
|
"bCC", "Branch Conditionally", conditionCodes = conditionCodesBcc,
|
||||||
IsaData("bsr", "Branch to Subroutine", opSize = "bsW"),
|
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(
|
IsaData(
|
||||||
"dbCC",
|
"dbCC",
|
||||||
"Test Condition, Decrement, and Branch",
|
"Test Condition, Decrement, and Branch",
|
||||||
altMnemonics = listOf("dbra"),
|
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(
|
||||||
IsaData("jsr", "Jump to Subroutine", opSize = ""),
|
"jmp", "Jump",
|
||||||
IsaData("nop", "No Operation", opSize = "", hasOps = false),
|
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("rtr", "Return and Restore", hasOps = false, modes = listOf(AllowedAdrMode(size = OP_UNSIZED, modInfo = RWM_MODIFY_STACK))),
|
||||||
IsaData("rts", "Return from Subroutine", hasOps = false),
|
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
|
// System Control Instructions
|
||||||
IsaData("andi", "AND Immediate to Status Register", id = "andi to SR", altMnemonics = listOf("and"), isPrivileged = true),
|
IsaData(
|
||||||
IsaData("eori", "Exclusive-OR Immediate to Status Register", id = "eori to SR", altMnemonics = listOf("eor"), isPrivileged = true),
|
"andi", "AND Immediate to Status Register", id = "andi to SR", altMnemonics = listOf("and"), isPrivileged = true,
|
||||||
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"),
|
),
|
||||||
IsaData("move", "Move to Status Register", id = "move to SR", isPrivileged = true),
|
IsaData(
|
||||||
IsaData("move", "Move User Stack Pointer", id = "move USP", isPrivileged = true),
|
"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("reset", "Reset External Devices", isPrivileged = true, hasOps = false, modes = NO_OPS_UNSIZED),
|
||||||
IsaData("rte", "Return from Exception", isPrivileged = true, hasOps = false),
|
IsaData(
|
||||||
IsaData("stop", "Stop", opSize = "", isPrivileged = true),
|
"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(
|
||||||
IsaData("illegal", "Take Illegal Instruction Trap", opSize = "", hasOps = false),
|
"chk", "Check Register Against Bound",
|
||||||
IsaData("trap", "Trap", opSize = ""),
|
modes = listOf(AllowedAdrMode(ALL_EXCEPT_AREG, DREG_ONLY, OP_SIZE_W, modInfo = RWM_READ_OP1_W or RWM_READ_OP2_W))
|
||||||
IsaData("trapv", "Trap on Overflow", opSize = ""),
|
),
|
||||||
|
IsaData("illegal", "Take Illegal Instruction Trap", hasOps = false, modes = NO_OPS_UNSIZED),
|
||||||
IsaData("andi", "AND Immediate to Condition Code Register", id = "andi to CCR", altMnemonics = listOf("and")),
|
IsaData("trap", "Trap", modes = listOf(AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), null, OP_UNSIZED))),
|
||||||
IsaData("eori", "Exclusive-OR Immediate to Condition Code Register", id = "eori to CCR", altMnemonics = listOf("eor")),
|
IsaData("trapv", "Trap on Overflow", hasOps = false, modes = NO_OPS_UNSIZED),
|
||||||
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(
|
||||||
|
"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
|
// 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 =
|
val mnemonics =
|
||||||
isaData.asSequence()
|
isaData.asSequence()
|
||||||
@@ -161,4 +734,54 @@ object M68kIsa {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
.toSet()
|
.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)))
|
||||||
}
|
}
|
||||||
+9
-2
@@ -4,13 +4,20 @@ import com.intellij.codeInsight.completion.*
|
|||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.patterns.PlatformPatterns
|
import com.intellij.patterns.PlatformPatterns
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import de.platon42.intellij.plugins.m68k.M68kIcons
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
||||||
|
|
||||||
class M68kMnemonicCompletionContributor : CompletionContributor() {
|
class M68kMnemonicCompletionContributor : CompletionContributor() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val MNEMONICS = M68kIsa.mnemonics
|
||||||
|
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.MNEMONIC), 10.0) }
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
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) {
|
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
|
||||||
resultSet.addAllElements(M68kIsa.mnemonics.map(LookupElementBuilder::create))
|
resultSet.addAllElements(MNEMONICS)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+102
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+244
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -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 com.intellij.psi.tree.IElementType
|
||||||
import de.platon42.intellij.plugins.m68k.asm.AssemblerDirectives
|
import de.platon42.intellij.plugins.m68k.asm.AssemblerDirectives
|
||||||
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.mnemonics
|
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.mnemonics
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
||||||
|
|
||||||
object LexerUtil {
|
object LexerUtil {
|
||||||
|
|
||||||
private val ASSIGNMENT_SEPARATORS = charArrayOf(' ', '\t', '=', ':')
|
private val ASSIGNMENT_SEPARATORS = charArrayOf(' ', '\t', '=', ':')
|
||||||
|
private val TOKEN_SEPARATORS = charArrayOf(' ', '\t', ':')
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun isAsmMnemonic(text: CharSequence) = mnemonics.contains(text.toString().lowercase())
|
fun isAsmMnemonic(text: CharSequence) = mnemonics.contains(text.toString().lowercase())
|
||||||
@@ -28,6 +30,11 @@ object LexerUtil {
|
|||||||
return text.length - text.indexOfAny(ASSIGNMENT_SEPARATORS)
|
return text.length - text.indexOfAny(ASSIGNMENT_SEPARATORS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun pushbackAfterFirstToken(text: CharSequence): Int {
|
||||||
|
return text.length - text.indexOfAny(TOKEN_SEPARATORS)
|
||||||
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun pushbackLabelColons(text: CharSequence): Int {
|
fun pushbackLabelColons(text: CharSequence): Int {
|
||||||
return text.count { it == ':' }
|
return text.count { it == ':' }
|
||||||
@@ -38,7 +45,28 @@ object LexerUtil {
|
|||||||
if (!lexer.eatOneWhitespace && lexer.lexerPrefs.spaceIntroducesComment) {
|
if (!lexer.eatOneWhitespace && lexer.lexerPrefs.spaceIntroducesComment) {
|
||||||
lexer.yybegin(_M68kLexer.WAITEOL)
|
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
|
return TokenType.WHITE_SPACE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@ package de.platon42.intellij.plugins.m68k.lexer
|
|||||||
|
|
||||||
data class M68kLexerPrefs(
|
data class M68kLexerPrefs(
|
||||||
var spaceIntroducesComment: Boolean = false,
|
var spaceIntroducesComment: Boolean = false,
|
||||||
var maxLinesPerMacro: Int = 50,
|
var maxLinesPerMacro: Int = 250,
|
||||||
var macroSectionUnparsed: Boolean = false,
|
var macroSectionUnparsed: Boolean = false,
|
||||||
var macroParametersUnparsed: Boolean = true
|
var macroParametersUnparsed: Boolean = true
|
||||||
)
|
)
|
||||||
@@ -13,6 +13,9 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
|
|||||||
%{
|
%{
|
||||||
private M68kLexerPrefs lexerPrefs;
|
private M68kLexerPrefs lexerPrefs;
|
||||||
boolean eatOneWhitespace = false;
|
boolean eatOneWhitespace = false;
|
||||||
|
int macroLines = 0;
|
||||||
|
int exprState = 0;
|
||||||
|
int exprOpState = 0;
|
||||||
|
|
||||||
public M68kLexerPrefs getLexerPrefs()
|
public M68kLexerPrefs getLexerPrefs()
|
||||||
{
|
{
|
||||||
@@ -23,6 +26,12 @@ import static de.platon42.intellij.plugins.m68k.lexer.LexerUtil.*;
|
|||||||
this((java.io.Reader)null);
|
this((java.io.Reader)null);
|
||||||
this.lexerPrefs = lexerPrefs;
|
this.lexerPrefs = lexerPrefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startExpr(int newExprState, int newExprOpState) {
|
||||||
|
exprState = newExprState;
|
||||||
|
exprOpState = newExprOpState;
|
||||||
|
yybegin(exprState);
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%public
|
%public
|
||||||
@@ -38,10 +47,12 @@ WHITE_SPACE=\p{Blank}+
|
|||||||
AREG=(a[0-6])
|
AREG=(a[0-6])
|
||||||
DREG=(d[0-7])
|
DREG=(d[0-7])
|
||||||
ASSIGNMENT=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?((\p{Blank}+equ\p{Blank}+)|(\p{Blank}+set\p{Blank}+)|\p{Blank}*=\p{Blank}*))
|
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=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:?)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:?)
|
||||||
LOCAL_LABEL_WC=(\.([:letter:]|_)(([:letter:]|[:digit:])|_)*:)|(([:letter:]|_)(([:letter:]|[:digit:])|_)*\$:)
|
LOCAL_LABEL_WC=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:)
|
||||||
GLOBAL_LABEL=(([:letter:]|_)(([:letter:]|[:digit:])|_)*:?:?)
|
GLOBAL_LABEL=(([:letter:]|_)([:letter:]|[:digit:]|_)*:?:?)
|
||||||
GLOBAL_LABEL_WC=(([: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:])+)
|
//MNEMONIC=(([:letter:])+)
|
||||||
SYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$]))*)
|
SYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$]))*)
|
||||||
BONUSSYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$\.\\]))*)
|
BONUSSYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$\.\\]))*)
|
||||||
@@ -51,7 +62,7 @@ OPSIZE_BS=(\.[bs])
|
|||||||
OPSIZE_W=(\.w)
|
OPSIZE_W=(\.w)
|
||||||
OPSIZE_L=(\.l)
|
OPSIZE_L=(\.l)
|
||||||
BINARY=(%[01]+)
|
BINARY=(%[01]+)
|
||||||
HEXADECIMAL=(\$[0-9a-f]+)
|
HEXADECIMAL=(\$[0-9a-fA-F]+)
|
||||||
OCTAL=(@[0-7]+)
|
OCTAL=(@[0-7]+)
|
||||||
DECIMAL=([0-9]+)
|
DECIMAL=([0-9]+)
|
||||||
STRINGLIT=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")
|
STRINGLIT=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")
|
||||||
@@ -59,227 +70,159 @@ PLAINPARAM=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")|<([^
|
|||||||
COMMENT=([;].*+)
|
COMMENT=([;].*+)
|
||||||
HASH_COMMENT=([#;*].*+)
|
HASH_COMMENT=([#;*].*+)
|
||||||
SKIP_TO_EOL=[^\r\n]+
|
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> {
|
<YYINITIAL, NOSOL>
|
||||||
{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; }
|
|
||||||
{EOL} { yybegin(YYINITIAL); return WHITE_SPACE; }
|
{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; }
|
{HASH_COMMENT} { yybegin(YYINITIAL); return COMMENT; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<INSTRPART> {
|
<INSTRPART,ASMINSTR,MACROCALL,ASSIGNMENT,EXPR,EXPR_OP,ASMOPS,ASMOPS_OP>
|
||||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
{
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
{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; }
|
{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> {
|
<ASMINSTR> {
|
||||||
{WHITE_SPACE} { yybegin(ASMOPS); return WHITE_SPACE; }
|
{WHITE_SPACE} { startExpr(ASMOPS, ASMOPS_OP); return WHITE_SPACE; }
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
|
||||||
|
|
||||||
{OPSIZE_BS} { return OPSIZE_BS; }
|
{OPSIZE_BS} { return OPSIZE_BS; }
|
||||||
{OPSIZE_W} { return OPSIZE_W; }
|
{OPSIZE_W} { return OPSIZE_W; }
|
||||||
{OPSIZE_L} { return OPSIZE_L; }
|
{OPSIZE_L} { return OPSIZE_L; }
|
||||||
|
|
||||||
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<MACROCALL> {
|
<MACROCALL> {
|
||||||
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
|
||||||
|
|
||||||
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
|
|
||||||
|
|
||||||
"," { return SEPARATOR; }
|
"," { return SEPARATOR; }
|
||||||
|
|
||||||
{PLAINPARAM} { return STRINGLIT; }
|
{PLAINPARAM} { return STRINGLIT; }
|
||||||
}
|
}
|
||||||
|
|
||||||
<ASSIGNMENT> {
|
<ASSIGNMENT> {
|
||||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
"equ"|"set" { startExpr(EXPR, EXPR_OP); return EQU; }
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
|
||||||
|
|
||||||
"equ"|"set" { yybegin(EXPR); return EQU; }
|
|
||||||
|
|
||||||
":" { return COLON; }
|
":" { 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> {
|
<EXPR> {
|
||||||
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
{BONUSSYMBOL} { yybegin(exprOpState); return SYMBOL; }
|
||||||
{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; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<EXPR_OP> {
|
<EXPR_OP, ASMOPS_OP> {
|
||||||
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
"<<" { yybegin(exprState); return OP_AR_SHIFT_L; }
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
">>" { 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 COLON; }
|
||||||
// ";" { return SEMICOLON; }
|
// ";" { return SEMICOLON; }
|
||||||
// "[" { return SQUARE_L; }
|
// "[" { return SQUARE_L; }
|
||||||
// "]" { return SQUARE_R; }
|
// "]" { return SQUARE_R; }
|
||||||
"," { yybegin(EXPR); return SEPARATOR; }
|
"," { yybegin(exprState); return SEPARATOR; }
|
||||||
"(" { yybegin(EXPR); return ROUND_L; }
|
"(" { yybegin(exprState); return ROUND_L; }
|
||||||
")" { return ROUND_R; }
|
")" { return ROUND_R; }
|
||||||
// "." { return DOT; }
|
// "." { return DOT; }
|
||||||
// "$" { return DOLLAR; }
|
// "$" { return DOLLAR; }
|
||||||
"~" { yybegin(EXPR); return OP_UNARY_COMPL; }
|
"~" { yybegin(exprState); return OP_UNARY_COMPL; }
|
||||||
"+" { yybegin(EXPR); return OP_PLUS; }
|
"+" { yybegin(exprState); return OP_PLUS; }
|
||||||
"-" { yybegin(EXPR); return OP_MINUS; }
|
"-" { yybegin(exprState); return OP_MINUS; }
|
||||||
"*" { yybegin(EXPR); return OP_AR_MUL; }
|
"*" { yybegin(exprState); return OP_AR_MUL; }
|
||||||
"%"|"//" { yybegin(EXPR); return OP_AR_MOD; }
|
"%"|"//" { yybegin(exprState); return OP_AR_MOD; }
|
||||||
"/" { yybegin(EXPR); return OP_AR_DIV; }
|
"/" { yybegin(exprState); return OP_AR_DIV; }
|
||||||
|
|
||||||
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<ASMOPS> {
|
<ASMOPS> {
|
||||||
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
{AREG} { yybegin(exprOpState); return AREG; }
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
{DREG} { yybegin(exprOpState); return DREG; }
|
||||||
|
"sp"|"a7" { yybegin(exprOpState); return REG_SP; }
|
||||||
{BINARY} { yybegin(ASMOPS_OP); return BINARY; }
|
"pc" { yybegin(exprOpState); return PC; }
|
||||||
{HEXADECIMAL} { yybegin(ASMOPS_OP); return HEXADECIMAL; }
|
"ccr" { yybegin(exprOpState); return REG_CCR; }
|
||||||
{OCTAL} { yybegin(ASMOPS_OP); return OCTAL; }
|
"sr" { yybegin(exprOpState); return REG_SR; }
|
||||||
{DECIMAL} { yybegin(ASMOPS_OP); return DECIMAL; }
|
"usp" { yybegin(exprOpState); return REG_USP; }
|
||||||
{STRINGLIT} { yybegin(ASMOPS_OP); return STRINGLIT; }
|
"vbr" { yybegin(exprOpState); return REG_VBR; }
|
||||||
|
|
||||||
{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; }
|
|
||||||
|
|
||||||
"#" { return HASH; }
|
"#" { return HASH; }
|
||||||
|
|
||||||
{SYMBOL} { yybegin(ASMOPS_OP); return SYMBOL; }
|
{SYMBOL} { yybegin(exprOpState); return SYMBOL; }
|
||||||
|
|
||||||
{COMMENT} { yybegin(WAITEOL); return COMMENT; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<ASMOPS_OP> {
|
<ASMOPS_OP> {
|
||||||
{WHITE_SPACE} { return handleEolCommentWhitespace(this); }
|
|
||||||
{EOL} { yybegin(YYINITIAL); return EOL; }
|
|
||||||
|
|
||||||
{OPSIZE_BS} { return OPSIZE_BS; }
|
{OPSIZE_BS} { return OPSIZE_BS; }
|
||||||
{OPSIZE_W} { return OPSIZE_W; }
|
{OPSIZE_W} { return OPSIZE_W; }
|
||||||
{OPSIZE_L} { return OPSIZE_L; }
|
{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>
|
<WAITEOL>
|
||||||
@@ -288,4 +231,35 @@ SKIP_TO_EOL=[^\r\n]+
|
|||||||
{SKIP_TO_EOL} { return COMMENT; }
|
{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; }
|
[^] { return BAD_CHARACTER; }
|
||||||
|
|||||||
@@ -118,7 +118,7 @@
|
|||||||
|
|
||||||
M68kFile ::= line*
|
M68kFile ::= line*
|
||||||
|
|
||||||
private line ::= !<<eof>> statement (<<eof>>|EOL)
|
private line ::= !<<eof>> (MacroDefinition | statement) (<<eof>>|EOL)
|
||||||
|
|
||||||
statement ::= (Assignment
|
statement ::= (Assignment
|
||||||
| PreprocessorDirective
|
| PreprocessorDirective
|
||||||
@@ -161,16 +161,40 @@ GlobalLabel ::= GLOBAL_LABEL_DEF COLON* {
|
|||||||
|
|
||||||
private Label ::= LocalLabel | GlobalLabel
|
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" }
|
AddressSize ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
|
||||||
DataWidth ::= (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)
|
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
||||||
PreprocessorOperands?
|
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?
|
AsmInstruction ::= AsmOp AsmOperands?
|
||||||
private Instruction ::= AsmInstruction | MacroCall
|
private Instruction ::= AsmInstruction | MacroCall
|
||||||
//external Instruction ::= parseMacroCallOrAsmInstruction
|
//external Instruction ::= parseMacroCallOrAsmInstruction
|
||||||
@@ -180,7 +204,7 @@ private AsmOperands ::= AddressingMode (SEPARATOR AddressingMode)?
|
|||||||
private PreprocessorOperands ::= PreprocessorOperand (SEPARATOR PreprocessorOperand)*
|
private PreprocessorOperands ::= PreprocessorOperand (SEPARATOR PreprocessorOperand)*
|
||||||
private PreprocessorOperand ::= expr
|
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
|
// TODO This should probably be a ILazyParseableElementType, no idea how to implement that yet
|
||||||
SymbolReference ::= SYMBOL {
|
SymbolReference ::= SYMBOL {
|
||||||
@@ -210,6 +234,14 @@ Register ::= DataRegister | AddressRegister | SpecialRegister
|
|||||||
|
|
||||||
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
|
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
|
||||||
|
|
||||||
|
IndexRegister ::= DataOrAddressRegister DataWidth?
|
||||||
|
{
|
||||||
|
name = "index register"
|
||||||
|
methods = [
|
||||||
|
isLongWidth
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
AddressingMode ::= ImmediateData
|
AddressingMode ::= ImmediateData
|
||||||
| AddressRegisterIndirectPreDecAddressingMode
|
| AddressRegisterIndirectPreDecAddressingMode
|
||||||
| AddressRegisterIndirectPostIncAddressingMode
|
| AddressRegisterIndirectPostIncAddressingMode
|
||||||
@@ -231,20 +263,108 @@ AddressingMode ::= ImmediateData
|
|||||||
SpecialRegisterDirectAddressingMode ::= SpecialRegister
|
SpecialRegisterDirectAddressingMode ::= SpecialRegister
|
||||||
DataRegisterDirectAddressingMode ::= DataRegister !(OP_MINUS|OP_AR_DIV)
|
DataRegisterDirectAddressingMode ::= DataRegister !(OP_MINUS|OP_AR_DIV)
|
||||||
AddressRegisterDirectAddressingMode ::= AddressRegister !(OP_MINUS|OP_AR_DIV)
|
AddressRegisterDirectAddressingMode ::= AddressRegister !(OP_MINUS|OP_AR_DIV)
|
||||||
AddressRegisterIndirectAddressingMode ::= ROUND_L AddressRegister ROUND_R !OP_PLUS
|
AddressRegisterIndirectAddressingMode ::= ROUND_L AddressRegister ROUND_R !OP_PLUS { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
|
||||||
AddressRegisterIndirectPostIncAddressingMode ::= ROUND_L AddressRegister ROUND_R OP_PLUS
|
AddressRegisterIndirectPostIncAddressingMode ::= ROUND_L AddressRegister ROUND_R OP_PLUS { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
|
||||||
AddressRegisterIndirectPreDecAddressingMode ::= OP_MINUS ROUND_L AddressRegister ROUND_R
|
AddressRegisterIndirectPreDecAddressingMode ::= OP_MINUS ROUND_L AddressRegister ROUND_R { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
|
||||||
AddressRegisterIndirectWithDisplacementOldAddressingMode ::= expr ROUND_L AddressRegister ROUND_R
|
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
|
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)
|
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
|
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
|
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 {
|
ImmediateData ::= HASH expr {
|
||||||
name = "immediate data"
|
name = "immediate data"
|
||||||
extends = AddressingMode
|
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)!!
|
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 {
|
fun createFile(project: Project, content: String): M68kFile {
|
||||||
return PsiFileFactory.getInstance(project).createFileFromText("dummy.m68k", INSTANCE, content) as 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.stubs.StubIndex
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
|
import de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex
|
||||||
|
import de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex
|
||||||
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
|
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
|
||||||
|
|
||||||
object M68kLookupUtil {
|
object M68kLookupUtil {
|
||||||
@@ -93,4 +94,47 @@ object M68kLookupUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findAllSymbolDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
|
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.psi.PsiElement
|
||||||
import com.intellij.util.IncorrectOperationException
|
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.createGlobalLabel
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createLocalLabel
|
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
|
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createSymbolDefinition
|
||||||
|
|
||||||
object M68kPsiImplUtil {
|
object M68kPsiImplUtil {
|
||||||
@@ -71,4 +73,71 @@ object M68kPsiImplUtil {
|
|||||||
val text = element.firstChild.text
|
val text = element.firstChild.text
|
||||||
return text.startsWith('.') || text.endsWith('$')
|
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(
|
override fun getPattern(): ElementPattern<out PsiElement?> = StandardPatterns.or(
|
||||||
PlatformPatterns.psiElement(M68kGlobalLabel::class.java),
|
PlatformPatterns.psiElement(M68kGlobalLabel::class.java),
|
||||||
PlatformPatterns.psiElement(M68kLocalLabel::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 {
|
override fun isInputValid(newName: String, element: PsiElement, context: ProcessingContext): Boolean {
|
||||||
return when (element) {
|
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()
|
is M68kLocalLabel -> LOCAL_LABEL_PATTERN.matcher(newName).matches()
|
||||||
else -> false
|
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
|
||||||
|
}
|
||||||
+10
-11
@@ -1,8 +1,7 @@
|
|||||||
package de.platon42.intellij.plugins.m68k.refs
|
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.navigation.NavigationItem
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.stubs.StubIndex
|
import com.intellij.psi.stubs.StubIndex
|
||||||
import com.intellij.util.Processor
|
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.M68kGlobalLabelStubIndex
|
||||||
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
|
import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
|
||||||
|
|
||||||
class M68kChooseByNameContributor : ChooseByNameContributorEx2 {
|
class M68kChooseByNameContributor : ChooseByNameContributorEx {
|
||||||
|
|
||||||
override fun processNames(processor: Processor<in String>, parameters: FindSymbolParameters) {
|
// override fun processNames(processor: Processor<in String>, parameters: FindSymbolParameters) {
|
||||||
processNames(processor, parameters.searchScope, parameters.idFilter)
|
// processNames(processor, parameters.searchScope, parameters.idFilter)
|
||||||
}
|
// }
|
||||||
|
|
||||||
override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
|
// override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
|
||||||
val result: MutableList<NavigationItem> = ArrayList()
|
// val result: MutableList<NavigationItem> = ArrayList()
|
||||||
processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
|
// processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
|
||||||
return result.toTypedArray()
|
// return result.toTypedArray()
|
||||||
}
|
// }
|
||||||
|
|
||||||
override fun processNames(processor: Processor<in String>, scope: GlobalSearchScope, filter: IdFilter?) {
|
override fun processNames(processor: Processor<in String>, scope: GlobalSearchScope, filter: IdFilter?) {
|
||||||
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, processor, scope, filter)
|
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, processor, scope, filter)
|
||||||
|
|||||||
+2
-2
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.refs
|
|||||||
import com.intellij.codeInsight.completion.*
|
import com.intellij.codeInsight.completion.*
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.icons.AllIcons
|
|
||||||
import com.intellij.patterns.PlatformPatterns
|
import com.intellij.patterns.PlatformPatterns
|
||||||
import com.intellij.util.ProcessingContext
|
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.M68kLookupUtil
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class M68kGlobalLabelSymbolCompletionContributor : CompletionContributor() {
|
|||||||
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
|
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
|
||||||
"pc"
|
"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 {
|
init {
|
||||||
|
|||||||
+19
-12
@@ -7,12 +7,14 @@ import com.intellij.psi.PsiPolyVariantReferenceBase
|
|||||||
import com.intellij.psi.ResolveResult
|
import com.intellij.psi.ResolveResult
|
||||||
import com.intellij.psi.impl.source.resolve.ResolveCache
|
import com.intellij.psi.impl.source.resolve.ResolveCache
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.PsiSearchHelper
|
import com.intellij.psi.stubs.StubIndex
|
||||||
import com.intellij.psi.search.UsageSearchContext
|
|
||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
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.M68kSymbolDefinition
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
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) :
|
class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
|
||||||
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
|
PsiPolyVariantReferenceBase<M68kSymbolReference>(element, TextRange(0, element.textLength)) {
|
||||||
@@ -24,18 +26,23 @@ class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
|
|||||||
class Resolver : ResolveCache.PolyVariantResolver<M68kGlobalLabelSymbolReference> {
|
class Resolver : ResolveCache.PolyVariantResolver<M68kGlobalLabelSymbolReference> {
|
||||||
override fun resolve(ref: M68kGlobalLabelSymbolReference, incompleteCode: Boolean): Array<ResolveResult> {
|
override fun resolve(ref: M68kGlobalLabelSymbolReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||||
val refName = ref.element.symbolName
|
val refName = ref.element.symbolName
|
||||||
|
|
||||||
val project = ref.element.project
|
val project = ref.element.project
|
||||||
val targets: MutableList<PsiElement> = SmartList()
|
|
||||||
PsiSearchHelper.getInstance(project).processElementsWithWord(
|
val targets: MutableList<M68kNamedElement> = SmartList()
|
||||||
{ elem, _ ->
|
StubIndex.getInstance()
|
||||||
when (elem) {
|
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
|
||||||
is M68kGlobalLabel, is M68kSymbolDefinition -> targets.add(elem)
|
{
|
||||||
}
|
targets.add(it)
|
||||||
true
|
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
|
return targets
|
||||||
.map(::PsiElementResolveResult)
|
.map(::PsiElementResolveResult)
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
|
|||||||
+19
@@ -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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -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.patterns.PlatformPatterns
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kMacroCall
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference
|
||||||
|
|
||||||
class M68kReferenceContributor : PsiReferenceContributor() {
|
class M68kReferenceContributor : PsiReferenceContributor() {
|
||||||
@@ -10,11 +11,13 @@ class M68kReferenceContributor : PsiReferenceContributor() {
|
|||||||
companion object {
|
companion object {
|
||||||
val localLabelReferenceProvider = LocalLabelReferenceProvider()
|
val localLabelReferenceProvider = LocalLabelReferenceProvider()
|
||||||
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
|
val globalLabelReferenceProvider = GlobalLabelSymbolReferenceProvider()
|
||||||
|
val macroReferenceProvider = MacroReferenceProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), localLabelReferenceProvider)
|
||||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kSymbolReference::class.java), globalLabelReferenceProvider)
|
||||||
|
registrar.registerReferenceProvider(PlatformPatterns.psiElement(M68kMacroCall::class.java), macroReferenceProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
class LocalLabelReferenceProvider : PsiReferenceProvider() {
|
class LocalLabelReferenceProvider : PsiReferenceProvider() {
|
||||||
@@ -32,4 +35,9 @@ class M68kReferenceContributor : PsiReferenceContributor() {
|
|||||||
return arrayOf(M68kGlobalLabelSymbolReference(symbolReference))
|
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 =
|
override fun getWordsScanner(): WordsScanner =
|
||||||
DefaultWordsScanner(
|
DefaultWordsScanner(
|
||||||
M68kLexer(M68kLexerPrefs()), // FIXME Oh no! More Prefs!
|
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.COMMENT),
|
||||||
TokenSet.create(M68kTypes.STRINGLIT, M68kTypes.DECIMAL, M68kTypes.HEXADECIMAL, M68kTypes.OCTAL, M68kTypes.BINARY),
|
TokenSet.create(M68kTypes.STRINGLIT, M68kTypes.DECIMAL, M68kTypes.HEXADECIMAL, M68kTypes.OCTAL, M68kTypes.BINARY),
|
||||||
TokenSet.EMPTY
|
TokenSet.EMPTY
|
||||||
@@ -32,6 +32,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
|
|||||||
is M68kLocalLabel -> "local label"
|
is M68kLocalLabel -> "local label"
|
||||||
is M68kSymbolDefinition -> "symbol definition"
|
is M68kSymbolDefinition -> "symbol definition"
|
||||||
is M68kSymbolReference -> "symbol reference"
|
is M68kSymbolReference -> "symbol reference"
|
||||||
|
is M68kMacroDefinition -> "macro definition"
|
||||||
|
is M68kMacroCall -> "macro call"
|
||||||
is M68kRegister -> "register"
|
is M68kRegister -> "register"
|
||||||
is M68kRefExpr -> "reference expression"
|
is M68kRefExpr -> "reference expression"
|
||||||
else -> ""
|
else -> ""
|
||||||
@@ -44,6 +46,8 @@ class M68kFindUsagesProvider : FindUsagesProvider {
|
|||||||
is M68kLocalLabel -> element.name!!
|
is M68kLocalLabel -> element.name!!
|
||||||
is M68kSymbolDefinition -> element.parent.text
|
is M68kSymbolDefinition -> element.parent.text
|
||||||
is M68kSymbolReference -> element.symbolName
|
is M68kSymbolReference -> element.symbolName
|
||||||
|
is M68kMacroDefinition -> element.macroNameDefinition.text
|
||||||
|
is M68kMacroCall -> element.macroName
|
||||||
is M68kRefExpr -> element.symbolReference?.symbolName ?: ""
|
is M68kRefExpr -> element.symbolReference?.symbolName ?: ""
|
||||||
is M68kRegister -> element.text
|
is M68kRegister -> element.text
|
||||||
else -> ""
|
else -> ""
|
||||||
|
|||||||
+3
-3
@@ -4,7 +4,6 @@ import com.intellij.ide.structureView.StructureViewTreeElement
|
|||||||
import com.intellij.ide.util.treeView.smartTree.TreeElement
|
import com.intellij.ide.util.treeView.smartTree.TreeElement
|
||||||
import com.intellij.navigation.ItemPresentation
|
import com.intellij.navigation.ItemPresentation
|
||||||
import com.intellij.psi.NavigatablePsiElement
|
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.M68kFile
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
|
import de.platon42.intellij.plugins.m68k.psi.M68kLookupUtil
|
||||||
@@ -19,8 +18,9 @@ class M68kStructureViewElement(private val myElement: NavigatablePsiElement) : S
|
|||||||
return when (myElement) {
|
return when (myElement) {
|
||||||
is M68kFile -> {
|
is M68kFile -> {
|
||||||
listOf(
|
listOf(
|
||||||
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.startOffset },
|
M68kLookupUtil.findAllSymbolDefinitions(myElement).sortedBy { it.textRange.startOffset },
|
||||||
M68kLookupUtil.findAllGlobalLabels(myElement).sortedBy { it.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.findAllSymbolDefinitions(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! }),
|
||||||
// M68kLookupUtil.findAllGlobalLabels(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! })
|
// M68kLookupUtil.findAllGlobalLabels(myElement).sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name!! })
|
||||||
)
|
)
|
||||||
|
|||||||
+60
-6
@@ -3,23 +3,77 @@ package de.platon42.intellij.plugins.m68k.structureview
|
|||||||
import com.intellij.ide.structureView.StructureViewModel.ElementInfoProvider
|
import com.intellij.ide.structureView.StructureViewModel.ElementInfoProvider
|
||||||
import com.intellij.ide.structureView.StructureViewModelBase
|
import com.intellij.ide.structureView.StructureViewModelBase
|
||||||
import com.intellij.ide.structureView.StructureViewTreeElement
|
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.openapi.editor.Editor
|
||||||
import com.intellij.psi.PsiFile
|
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.M68kLocalLabel
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
|
||||||
|
|
||||||
class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
|
class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
|
||||||
StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider {
|
StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider {
|
||||||
|
|
||||||
override fun isAlwaysShowsPlus(element: StructureViewTreeElement): Boolean {
|
companion object {
|
||||||
return false
|
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 {
|
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> {
|
override fun getSorters(): Array<Sorter> = arrayOf(Sorter.ALPHA_SORTER)
|
||||||
return 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 com.intellij.psi.tree.ILightStubFileElementType
|
||||||
import de.platon42.intellij.plugins.m68k.MC68000Language.Companion.INSTANCE
|
import de.platon42.intellij.plugins.m68k.MC68000Language.Companion.INSTANCE
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
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.M68kSymbolDefinition
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
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.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.psi.impl.M68kSymbolDefinitionImpl
|
||||||
import de.platon42.intellij.plugins.m68k.stubs.impl.M68kGlobalLabelStubImpl
|
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 de.platon42.intellij.plugins.m68k.stubs.impl.M68kSymbolDefinitionStubImpl
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@@ -67,5 +70,28 @@ interface M68kElementTypes {
|
|||||||
override fun indexStub(stub: M68kSymbolDefinitionStub, sink: IndexSink) = sink.occurrence(M68kSymbolDefinitionStubIndex.KEY, stub.name!!)
|
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) {
|
return when (name) {
|
||||||
"GLOBAL_LABEL" -> M68kElementTypes.GLOBAL_LABEL
|
"GLOBAL_LABEL" -> M68kElementTypes.GLOBAL_LABEL
|
||||||
"SYMBOL_DEFINITION" -> M68kElementTypes.SYMBOL_DEFINITION
|
"SYMBOL_DEFINITION" -> M68kElementTypes.SYMBOL_DEFINITION
|
||||||
|
"MACRO_DEFINITION" -> M68kElementTypes.MACRO_DEFINITION
|
||||||
else -> throw RuntimeException("Unknown element type '$name'")
|
else -> throw RuntimeException("Unknown element type '$name'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
@@ -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.GLOBAL_LABEL
|
||||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.LOCAL_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_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.MNEMONIC
|
||||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.NUMBER
|
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.NUMBER
|
||||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.OTHER_PREPROCESSOR
|
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.SPECIAL_REG
|
||||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.STACK_POINTER
|
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.STRING
|
||||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLDEF
|
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL_DEF
|
||||||
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOLREF
|
import de.platon42.intellij.plugins.m68k.syntax.M68kSyntaxHighlighter.Companion.SYMBOL_REF
|
||||||
import org.jetbrains.annotations.NonNls
|
import org.jetbrains.annotations.NonNls
|
||||||
import javax.swing.Icon
|
import javax.swing.Icon
|
||||||
|
|
||||||
@@ -49,7 +52,7 @@ PIC_HEIGHT = 256
|
|||||||
include "../includes/hardware/custom.i"
|
include "../includes/hardware/custom.i"
|
||||||
|
|
||||||
BLTHOGON MACRO ; macro definition
|
BLTHOGON MACRO ; macro definition
|
||||||
move.w #DMAF_SETCLR|DMAF_BLITHOG,dmacon(a5)
|
move.w #DMAF_SETCLR|DMAF_BLITHOG,dmacon(a5) ; hog!
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
demo_init ; global label
|
demo_init ; global label
|
||||||
@@ -99,9 +102,12 @@ hello: dc.b 'Hello World!',10,0
|
|||||||
AttributesDescriptor("Local labels", LOCAL_LABEL),
|
AttributesDescriptor("Local labels", LOCAL_LABEL),
|
||||||
AttributesDescriptor("Comma (separator)", SEPARATOR),
|
AttributesDescriptor("Comma (separator)", SEPARATOR),
|
||||||
AttributesDescriptor("Colon", COLON),
|
AttributesDescriptor("Colon", COLON),
|
||||||
AttributesDescriptor("Symbol definition", SYMBOLDEF),
|
AttributesDescriptor("Symbol definition", SYMBOL_DEF),
|
||||||
AttributesDescriptor("Symbol reference", SYMBOLREF),
|
AttributesDescriptor("Symbol reference", SYMBOL_REF),
|
||||||
AttributesDescriptor("Assembly mnemonic", MNEMONIC),
|
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("Macro invocation", MACRO_CALL),
|
||||||
AttributesDescriptor("Data width: Byte/short", DATA_WIDTH_BS),
|
AttributesDescriptor("Data width: Byte/short", DATA_WIDTH_BS),
|
||||||
AttributesDescriptor("Data width: Word", DATA_WIDTH_W),
|
AttributesDescriptor("Data width: Word", DATA_WIDTH_W),
|
||||||
|
|||||||
@@ -28,11 +28,14 @@ class M68kSyntaxHighlighter(val project: Project?) : SyntaxHighlighterBase() {
|
|||||||
M68kTypes.COLON -> arrayOf(COLON)
|
M68kTypes.COLON -> arrayOf(COLON)
|
||||||
M68kTypes.GLOBAL_LABEL_DEF -> arrayOf(GLOBAL_LABEL)
|
M68kTypes.GLOBAL_LABEL_DEF -> arrayOf(GLOBAL_LABEL)
|
||||||
M68kTypes.LOCAL_LABEL_DEF -> arrayOf(LOCAL_LABEL)
|
M68kTypes.LOCAL_LABEL_DEF -> arrayOf(LOCAL_LABEL)
|
||||||
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOLDEF)
|
M68kTypes.SYMBOLDEF -> arrayOf(SYMBOL_DEF)
|
||||||
M68kTypes.SYMBOL -> arrayOf(SYMBOLREF)
|
M68kTypes.SYMBOL -> arrayOf(SYMBOL_REF)
|
||||||
M68kTypes.CURRENT_PC_SYMBOL, M68kTypes.PC -> arrayOf(PROGRAM_COUNTER)
|
M68kTypes.CURRENT_PC_SYMBOL, M68kTypes.PC -> arrayOf(PROGRAM_COUNTER)
|
||||||
M68kTypes.MNEMONIC -> arrayOf(MNEMONIC)
|
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.DATA_DIRECTIVE -> arrayOf(DATA_PREPROCESSOR)
|
||||||
M68kTypes.OTHER_DIRECTIVE, M68kTypes.EQU -> arrayOf(OTHER_PREPROCESSOR)
|
M68kTypes.OTHER_DIRECTIVE, M68kTypes.EQU -> arrayOf(OTHER_PREPROCESSOR)
|
||||||
M68kTypes.OPSIZE_BS -> arrayOf(DATA_WIDTH_BS)
|
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 LOCAL_LABEL = TextAttributesKey.createTextAttributesKey("MC68000_GLOBAL_LABEL", DefaultLanguageHighlighterColors.FUNCTION_DECLARATION)
|
||||||
val SEPARATOR = TextAttributesKey.createTextAttributesKey("MC68000_SEPARATOR", DefaultLanguageHighlighterColors.COMMA)
|
val SEPARATOR = TextAttributesKey.createTextAttributesKey("MC68000_SEPARATOR", DefaultLanguageHighlighterColors.COMMA)
|
||||||
val COLON = TextAttributesKey.createTextAttributesKey("MC68000_COLON", DefaultLanguageHighlighterColors.DOT)
|
val COLON = TextAttributesKey.createTextAttributesKey("MC68000_COLON", DefaultLanguageHighlighterColors.DOT)
|
||||||
val SYMBOLDEF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLDEF", DefaultLanguageHighlighterColors.CONSTANT)
|
val SYMBOL_DEF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLDEF", DefaultLanguageHighlighterColors.CONSTANT)
|
||||||
val SYMBOLREF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
|
val SYMBOL_REF = TextAttributesKey.createTextAttributesKey("MC68000_SYMBOLREF", DefaultLanguageHighlighterColors.IDENTIFIER)
|
||||||
val MNEMONIC = TextAttributesKey.createTextAttributesKey("MC68000_MNEMONIC", DefaultLanguageHighlighterColors.FUNCTION_CALL)
|
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 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_BS = TextAttributesKey.createTextAttributesKey("MC68000_DATA_WIDTH_BS", DefaultLanguageHighlighterColors.DOT)
|
||||||
val DATA_WIDTH_L = TextAttributesKey.createTextAttributesKey("MC68000_DATA_WIDTH_W", 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("?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<p>
|
<p>
|
||||||
<a href="https://github.com/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
|
<a href="https://github.com/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
|
||||||
]]></description>
|
]]></description>
|
||||||
<idea-version since-build="193.7288.0"/>
|
<idea-version since-build="203.5981.166"/>
|
||||||
|
|
||||||
<depends>com.intellij.modules.lang</depends>
|
<depends>com.intellij.modules.lang</depends>
|
||||||
|
|
||||||
@@ -24,18 +24,32 @@
|
|||||||
<colorSettingsPage implementation="de.platon42.intellij.plugins.m68k.syntax.M68kColorSettingsPage"/>
|
<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.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.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.braceMatcher language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.syntax.M68kPairedBraceMatcher"/>
|
||||||
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
|
<lang.quoteHandler language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.M68kStringQuoteHandler"/>
|
||||||
<lang.findUsagesProvider language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.scanner.M68kFindUsagesProvider"/>
|
<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.psiStructureViewFactory language="MC68000" implementationClass="de.platon42.intellij.plugins.m68k.structureview.M68kStructureViewFactory"/>
|
||||||
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
|
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kSymbolReference"
|
||||||
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
|
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"/>
|
<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.M68kGlobalLabelStubIndex"/>
|
||||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex"/>
|
<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"/>
|
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
|
||||||
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
||||||
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
|
<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>
|
</extensions>
|
||||||
|
|
||||||
<actions>
|
<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>
|
||||||
+20
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
+83
@@ -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>#<xxx></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>")
|
||||||
|
}
|
||||||
|
}
|
||||||
+102
@@ -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"> </td>
|
||||||
|
<td valign="top">
|
||||||
|
<div class="grayed">[...]</div>
|
||||||
|
</td>
|
||||||
|
<td valign="top"> </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">--></td>
|
||||||
|
<td valign="top"><b><code>move.w <font color="#ffc800">d0</font>,d1</code></b></td>
|
||||||
|
<td valign="top"> ; <--</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"> </td>
|
||||||
|
<td valign="top">
|
||||||
|
<div class="grayed">[...]</div>
|
||||||
|
</td>
|
||||||
|
<td valign="top"> </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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
+121
@@ -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
|
package de.platon42.intellij.plugins.m68k.parser
|
||||||
|
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import de.platon42.intellij.jupiter.MyTestCase
|
import de.platon42.intellij.jupiter.MyTestCase
|
||||||
import de.platon42.intellij.jupiter.ParsingTestExtension
|
import de.platon42.intellij.jupiter.ParsingTestExtension
|
||||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
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
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
@TestDataSubPath("addressingmodes")
|
@TestDataSubPath("addressingmodes")
|
||||||
@@ -85,7 +89,24 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
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
|
@Test
|
||||||
@@ -95,12 +116,17 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(testCase, " move.l usp,a0\n"
|
testGoodSyntax(
|
||||||
+ " move.l a5,usp\n")
|
testCase, " move.l usp,a0\n"
|
||||||
|
+ " move.l a5,usp\n"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun complex_math_expression_in_displacement(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
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")
|
testGoodSyntax(testCase, " dc.w *-.label\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun uppercase_hexadecimal_string(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
|
testGoodSyntax(testCase, " move.l #\$DEADBEEF,d0\n")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
internal fun if_with_single_equals_comparison(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun if_with_single_equals_comparison(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
testGoodSyntax(testCase, " IF DEBUG=1\n")
|
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")
|
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
|
@Test
|
||||||
internal fun putmsg_call_with_specially_bracketed_parameters(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
internal fun putmsg_call_with_specially_bracketed_parameters(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||||
// FIXME this doesn't work as intended...
|
// 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"""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+32
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
-4
@@ -8,10 +8,7 @@ import de.platon42.intellij.jupiter.MyFixture
|
|||||||
import de.platon42.intellij.jupiter.TestDataPath
|
import de.platon42.intellij.jupiter.TestDataPath
|
||||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||||
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
|
import de.platon42.intellij.plugins.m68k.AbstractM68kTest
|
||||||
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
import de.platon42.intellij.plugins.m68k.psi.*
|
||||||
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 org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
@@ -71,4 +68,22 @@ internal class M68kReferenceContributorTest : AbstractM68kTest() {
|
|||||||
|
|
||||||
myFixture.checkResultByFile("symbol_assignment_after_rename.asm")
|
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
Reference in New Issue
Block a user