Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c3daf28f7 | ||
|
|
1dcf288d27 | ||
|
|
2abb5af8b0 | ||
|
|
6c9a726b86 | ||
|
|
921449cbb8 | ||
|
|
6f99c2ffcc | ||
|
|
5881dcdaf8 | ||
|
|
71398f51d2 | ||
|
|
eb26793a20 | ||
|
|
954f42bf63 | ||
|
|
94001c8b87 | ||
|
|
55403f89a6 | ||
|
|
7744b589d4 | ||
|
|
19e3b519db | ||
|
|
587b284d25 | ||
|
|
719460ebfe | ||
|
|
44a4721d77 | ||
|
|
09a4e62c7c | ||
|
|
ce3cdbbed6 | ||
|
|
27b7593de8 | ||
|
|
3aeb415974 | ||
|
|
128330d2c7 | ||
|
|
ef900e9c19 |
+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,8 +1,8 @@
|
||||
# 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.).
|
||||
|
||||

|
||||

|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -19,20 +19,87 @@ awesome features and is pretty advanced. Check it out. You can install both plug
|
||||
|
||||
Big kudos to Yann -- a few features were _inspired_ by his code.
|
||||
|
||||
My plugin, on the other hand, is still pretty basic and is the result of about a week's effort. I released a really early first version it because I think
|
||||
it's "good enough" to get started, and I can return to demo coding with its current state.
|
||||
My plugin, on the other hand, is still pretty basic and is the result of a few weeks of work. I released a really early first version it because I think it's "
|
||||
good enough" to get started, and I can return to demo coding with its current state.
|
||||
|
||||
## Features
|
||||
|
||||
- Parser / Lexer for MC68000 (yes, only 68000 right now!) assembly language files in VAsm / DevPac style
|
||||
- Inspection for validating the syntax of the 68000 ISA.
|
||||
- Syntax highlighting and Color Settings Page (you should really modify the color settings to your likings!)
|
||||
- Mnemonics code completion
|
||||
- Symbols / Labels / Macros code completion
|
||||
- References / Refactoring support for local and global labels, symbol assignments, and macros.
|
||||
- Simple register usage flow (hover over register or press F1 for full flow)
|
||||
- Brace matching
|
||||
- Quote handler
|
||||
- Goto Symbol support
|
||||
- Structure view
|
||||
- Documentation provider for symbol definitions and mnemonics (listing available addressing modes etc.).
|
||||
|
||||
### Inspections
|
||||
|
||||
#### M68kSyntaxInspection - Assembly instruction validity
|
||||
|
||||
Checks the validity of the current instruction. If an instruction is not recognized, you may get one of the following errors:
|
||||
|
||||
- Instruction _mnemonic_ not supported on selected cpu (you won't get this currently as only MC68000 is supported)
|
||||
- No operands expected for _mnemonic_
|
||||
- Second operand _op_ unexpected for _mnemonic_
|
||||
- Unsupported addressing mode for _mnemonic_
|
||||
- Unsupported addressing mode _op_ for first operand of _mnemonic_
|
||||
- Unsupported addressing mode _op_ for second operand of _mnemonic_
|
||||
- Unsupported addressing modes for operands in this order for _mnemonic_ (try swapping)
|
||||
- Instruction _mnemonic_ is unsized (you tried to specify `.b`, `.w` or `.l`)
|
||||
- Operation size _(.b,.w,.l)_ unsupported for _mnemonic_
|
||||
- Operation size _(.b,.w,.l)_ unsupported (should be _(.b,.w,.l)_)
|
||||
|
||||
#### M68kDeadWriteInspection - Dead writes to registers
|
||||
|
||||
This inspection looks at register writes and tries to find instructions that renders a write moot because it was overwritten by another instruction before
|
||||
anything useful was done with it.
|
||||
|
||||
Analysis is aborted at global labels, flow control instructions, directives
|
||||
(e.g. conditional assembly) and macros with the register names as parameter.
|
||||
|
||||
The inspection tries to take condition code changing into account and puts out a weak warning if the statement merely changes condition codes before the
|
||||
contents of the register are overwritten. In this case, it is sometimes better to replace `move` by `tst`.
|
||||
|
||||
#### M68kUnexpectedConditionalInstructionInspection - Unaffected condition codes before conditional instruction
|
||||
|
||||
Especially for novice coders, it is not clear that some instructions do not affect the condition codes for a subsequent condition branch or `scc` instruction.
|
||||
`movea`, `adda` and `suba` come to my mind.
|
||||
|
||||
The inspection will report such suspicious instruction sequences.
|
||||
|
||||
However, this does not need to be a programming error. Advanced coders sometimes make use of the fact that instructions do not change condition codes and thus
|
||||
optimize the order of execution.
|
||||
|
||||
### Documentation provider
|
||||
|
||||
#### M68kSymbolDefinitionDocumentationProvider
|
||||
|
||||
Provides the assigned value of a `=`, `set` or `equ` symbol definition when hovering over a symbol.
|
||||
|
||||
#### M68kRegisterFlowDocumentationProvider
|
||||
|
||||
When hovering over or placing the cursor at a data or address register, the documentation will scan through the instructions backwards and forwards and will
|
||||
show all read, changes of the register contents. It does this until an instruction is found that defines (sets) the contents of the register
|
||||
(according to the size of the instruction where the cursor was placed).
|
||||
|
||||
The analysis ignores all code flow instructions and might be inaccurate for branches, macro use, etc. It also stops at global labels.
|
||||
|
||||
The documentation will search up to 100 instructions in each direction, but only four when hovering over the register
|
||||
(so if you need the whole analysis, use the documentation window).
|
||||
|
||||
#### M68kInstructionDocumentationProvider
|
||||
|
||||
When hovering over a mnemonic, it will show a short description of the assembly instruction.
|
||||
|
||||
For the documentation window, affected condition codes, allowed operation sizes and addressing modes are listed for the selected instruction
|
||||
(so only stuff from `cmpa` is listed when you're looking at a `cmp.w a0,a1` instruction).
|
||||
|
||||
If the current statement has no valid syntax, the instruction details of all matching mnemonics will be shown instead.
|
||||
|
||||
## Known issues
|
||||
|
||||
@@ -42,14 +109,14 @@ it's "good enough" to get started, and I can return to demo coding with its curr
|
||||
- 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 (default is off).
|
||||
- No support for other processor instructions, FPU or 68020+ address modes.
|
||||
- No semantic checking for allowed address modes or data widths yet.
|
||||
- Unit Test coverage is not as good as it could be (ahem).
|
||||
- `opt` keyword needs special treatment and will currently show a parsing error.
|
||||
- Missing but planned features:
|
||||
- Macro evaluation on invocation
|
||||
- Folding
|
||||
- Semantic inspections
|
||||
- Quick fixes
|
||||
- Formatter + Code Style Settings
|
||||
- More semantic inspections
|
||||
- Quick fixes
|
||||
- Maybe formatter + Code Style Settings
|
||||
- Register use analysis (but this only makes sense after macro evaluation)
|
||||
- Cycle counting
|
||||
|
||||
@@ -66,13 +133,47 @@ It is probably the only plugin (besides [Cajon](https://github.com/chrisly42/caj
|
||||
far (or at least the only one I'm aware of ;) ). The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing, and it took me quite a while to
|
||||
make it work with JUnit 5. Feel free to use the code (in package ```de.platon42.intellij.jupiter```) for your projects (with attribution).
|
||||
|
||||
## Private TODO list
|
||||
|
||||
- code completion suggestion for unresolved local labels, global labels and symbols
|
||||
- support `include` directive
|
||||
- support `opt` directive
|
||||
- suppression support via comments
|
||||
- inspection: Unresolved local label
|
||||
- inspection: Unresolved macro
|
||||
|
||||
## Changelog
|
||||
|
||||
### V0.5 (06-Aug-21)
|
||||
|
||||
- Bugfix: `movem` ISA was wrong regarding the `movem.w <ea>,<registerlist>` (sign extends registers).
|
||||
- Cosmetics: Changed Register Flow Documentation wording from _reads_ to _uses_ and from _modifies_ to _changes_.
|
||||
- Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
||||
- Bugfix: Added alternate condition code tests `HS (=CC)` and `LO (=CS)`.
|
||||
- Performance: Optimized mnemonic lookup.
|
||||
- Enhancement: Reworked Instruction Documentation provider, now shows condition codes.
|
||||
- Bugfix: In ISA `exg` is no longer treated as setting a definitive value.
|
||||
- New: Added inspection to find dead writes to registers!
|
||||
- New: Added inspection to warn about unexpected condition code unaffecting instructions before conditional instructions.
|
||||
|
||||
### 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.
|
||||
- Enhancement: Macro definition refactoring and find usages support.
|
||||
- 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.
|
||||
|
||||
+31
-25
@@ -7,7 +7,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = 'de.platon42'
|
||||
version = '0.3'
|
||||
version = '0.5'
|
||||
sourceCompatibility = "1.8"
|
||||
targetCompatibility = "1.8"
|
||||
|
||||
@@ -21,7 +21,7 @@ repositories {
|
||||
*/
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||
testImplementation "org.assertj:assertj-core:3.20.2"
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0-M1'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.0-M1'
|
||||
@@ -31,7 +31,10 @@ dependencies {
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs += "-Xjvm-default=all"
|
||||
}
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
@@ -39,42 +42,45 @@ compileTestKotlin {
|
||||
}
|
||||
|
||||
intellij {
|
||||
setVersion("2021.1.3") // LATEST-EAP-SNAPSHOT
|
||||
setVersion("2021.2") // LATEST-EAP-SNAPSHOT
|
||||
setUpdateSinceUntilBuild(false)
|
||||
// setPlugins(["com.intellij.java"])
|
||||
}
|
||||
|
||||
runPluginVerifier {
|
||||
ideVersions = ["IC-193.5662.53", "IC-211.7628.21", // 2019.3.1 - 2021.1.3
|
||||
"CL-193.5233.103", "CL-193.7288.25", // 2019.3
|
||||
"CL-201.6668.126", "CL-201.8743.17", // 2020.1
|
||||
"CL-202.6397.106", "CL-202.8194.17", // 2020.2
|
||||
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-211.6693.114", "CL-211.7628.27", // 2021.1
|
||||
"CL-212.4746.93"] // 2021.2
|
||||
downloadDir = System.getProperty("user.home") + "/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea"
|
||||
}
|
||||
|
||||
patchPluginXml {
|
||||
setChangeNotes("""
|
||||
<h4>V0.3 (28-Jul-21)</h4>
|
||||
<h4>V0.5 (06-Aug-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>Enhancement: 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.
|
||||
<li>Bugfix: movem ISA was wrong regarding movem.w <ea>,<registerlist> (sign extends registers).
|
||||
<li>Cosmetics: Changed Register Flow Documentation wording from 'reads' to 'uses' and from 'modifies' to 'changes'.
|
||||
<li>Bugfix: Minor fix for `andi/eori/ori to ccr` which were not byte sized in ISA.
|
||||
<li>Bugfix: Added alternate condition code tests HS (=CC) and LO (=CS).
|
||||
<li>Performance: Optimized mnemonic lookup.
|
||||
<li>Enhancement: Reworked Instruction Documentation provider, now shows condition codes.
|
||||
<li>Bugfix: In ISA exg is no longer treated as setting a definitive value.
|
||||
<li>New: Added inspection to find dead writes to registers!
|
||||
<li>New: Added inspection to warn about unexpected condition code unaffecting instructions before conditional instructions.
|
||||
</ul>
|
||||
<h4>V0.2 (27-Jul-21)</h4>
|
||||
<h4>V0.4 (03-Aug-21)</h4>
|
||||
<ul>
|
||||
<li>Cosmetics: Added (same) icon for plugin as for file type.
|
||||
<li>Performance: Use Word-Index for global labels and symbols instead of iterating over the file.
|
||||
<li>Performance: Use Stub-Index for global labels and symbols.
|
||||
<li>Bugfix: No longer reports a syntax error when file lacks terminating End-Of-Line.
|
||||
<li>Enhancement: Registers are now offered for code completion, making editing less annoying.
|
||||
<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>
|
||||
<p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p>
|
||||
""")
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 91 KiB |
@@ -137,12 +137,12 @@ public class _M68kLexer implements FlexLexer {
|
||||
|
||||
/* The ZZ_CMAP_A table has 3200 entries */
|
||||
static final char ZZ_CMAP_A[] = zzUnpackCMap(
|
||||
"\11\0\1\4\1\2\2\1\1\3\22\0\1\4\1\63\1\53\1\57\1\24\1\40\1\70\1\52\1\61\1\62" +
|
||||
"\1\67\1\65\1\56\1\66\1\23\1\72\2\41\5\6\1\10\2\45\1\14\1\32\1\54\1\22\1\55" +
|
||||
"\1\0\1\50\1\5\1\75\1\26\1\7\1\15\6\11\1\37\1\25\1\31\1\30\1\73\1\16\1\27\1" +
|
||||
"\20\1\21\1\17\1\74\1\36\3\11\1\0\1\33\1\0\1\60\1\12\1\51\1\42\1\34\1\47\1" +
|
||||
"\43\1\46\1\44\5\11\1\37\1\25\1\31\1\30\1\73\1\16\1\27\1\35\1\21\1\17\1\74" +
|
||||
"\1\36\3\11\1\0\1\71\1\0\1\64\6\0\1\1\12\0\1\4\11\0\1\11\12\0\1\11\4\0\1\11" +
|
||||
"\11\0\1\4\1\2\2\1\1\3\22\0\1\4\1\57\1\47\1\53\1\24\1\40\1\64\1\46\1\55\1\56" +
|
||||
"\1\63\1\61\1\52\1\62\1\23\1\66\2\41\5\6\1\10\2\43\1\14\1\32\1\50\1\22\1\51" +
|
||||
"\1\0\1\44\1\5\1\71\1\26\1\7\1\15\1\42\5\11\1\37\1\25\1\31\1\30\1\67\1\16\1" +
|
||||
"\27\1\20\1\21\1\17\1\70\1\36\3\11\1\0\1\33\1\0\1\54\1\12\1\45\1\5\1\34\1\26" +
|
||||
"\1\7\1\15\1\42\5\11\1\37\1\25\1\31\1\30\1\67\1\16\1\27\1\35\1\21\1\17\1\70" +
|
||||
"\1\36\3\11\1\0\1\65\1\0\1\60\6\0\1\1\12\0\1\4\11\0\1\11\12\0\1\11\4\0\1\11" +
|
||||
"\5\0\27\11\1\0\27\11\1\20\2\11\4\0\14\11\16\0\5\11\7\0\1\11\1\0\1\11\1\0\5" +
|
||||
"\11\1\0\2\11\2\0\4\11\1\0\1\11\6\0\1\11\1\0\3\11\1\0\1\11\1\0\4\11\1\0\23" +
|
||||
"\11\1\0\13\11\10\0\6\11\1\0\26\11\2\0\1\11\6\0\10\11\10\0\13\11\5\0\3\11\15" +
|
||||
@@ -207,13 +207,13 @@ public class _M68kLexer implements FlexLexer {
|
||||
"\1\71\1\16\1\72\1\73\1\16\1\74\1\75\2\0" +
|
||||
"\1\76\4\0\1\77\1\16\1\32\1\100\1\101\1\102" +
|
||||
"\1\103\1\104\1\105\1\106\3\0\1\52\1\0\1\52" +
|
||||
"\1\0\1\52\1\0\1\52\1\55\1\57\4\0\1\4" +
|
||||
"\1\0\1\52\1\0\1\52\1\55\1\57\3\0\1\4" +
|
||||
"\1\62\1\63\1\7\1\107\1\7\1\110\1\111\1\112" +
|
||||
"\1\113\1\0\1\52\3\0\1\55\1\57\3\0\1\7" +
|
||||
"\1\55\1\57\2\0\1\114\1\115\1\116\1\0\1\117";
|
||||
|
||||
private static int[] zzUnpackAction() {
|
||||
int[] result = new int[185];
|
||||
int[] result = new int[184];
|
||||
int offset = 0;
|
||||
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -238,33 +238,32 @@ public class _M68kLexer implements FlexLexer {
|
||||
private static final int[] ZZ_ROWMAP = zzUnpackRowMap();
|
||||
|
||||
private static final String ZZ_ROWMAP_PACKED_0 =
|
||||
"\0\0\0\76\0\174\0\272\0\370\0\u0136\0\u0174\0\u01b2" +
|
||||
"\0\u01f0\0\u022e\0\u026c\0\u02aa\0\u02e8\0\u0326\0\u0364\0\u03a2" +
|
||||
"\0\u03a2\0\u03e0\0\u041e\0\u045c\0\u049a\0\u04d8\0\u0516\0\u0554" +
|
||||
"\0\u0592\0\u05d0\0\u060e\0\u03a2\0\u064c\0\u068a\0\u06c8\0\u03a2" +
|
||||
"\0\u0706\0\u0744\0\u0782\0\u07c0\0\u07fe\0\u083c\0\u087a\0\u08b8" +
|
||||
"\0\u08f6\0\u0934\0\u0972\0\u09b0\0\u09ee\0\u0a2c\0\u0a6a\0\u0aa8" +
|
||||
"\0\u0ae6\0\u03a2\0\u03a2\0\u03a2\0\u03a2\0\u03a2\0\u03a2\0\u03a2" +
|
||||
"\0\u03a2\0\u03a2\0\u03a2\0\u0b24\0\u0b62\0\u0ba0\0\u03a2\0\u0bde" +
|
||||
"\0\u0c1c\0\u03a2\0\u03a2\0\u03a2\0\u03a2\0\u0c5a\0\u03a2\0\u03a2" +
|
||||
"\0\u03a2\0\u03a2\0\u0c98\0\u0cd6\0\u0d14\0\u0d52\0\u0d90\0\u03a2" +
|
||||
"\0\u0dce\0\u0e0c\0\u0e0c\0\u0e4a\0\u0e88\0\u0ec6\0\u0f04\0\u0f42" +
|
||||
"\0\u0f42\0\u03a2\0\u0f80\0\u0fbe\0\u0ffc\0\u103a\0\u1078\0\u1078" +
|
||||
"\0\u03a2\0\u10b6\0\u10f4\0\u0f42\0\u1132\0\u1170\0\u11ae\0\u11ec" +
|
||||
"\0\u122a\0\u1268\0\u12a6\0\u12e4\0\u1322\0\u1360\0\u03a2\0\u03a2" +
|
||||
"\0\u03a2\0\u08b8\0\u08b8\0\u08b8\0\u139e\0\u08b8\0\u0972\0\u13dc" +
|
||||
"\0\u09ee\0\u0a2c\0\u0a6a\0\u141a\0\u03a2\0\u0aa8\0\u1458\0\u0ae6" +
|
||||
"\0\u1496\0\u08b8\0\u14d4\0\u03a2\0\u03a2\0\u03a2\0\u03a2\0\u03a2" +
|
||||
"\0\u03a2\0\u03a2\0\u03a2\0\u1512\0\u1550\0\u158e\0\u15cc\0\u160a" +
|
||||
"\0\u1648\0\u1686\0\u16c4\0\u1702\0\u1740\0\u177e\0\u17bc\0\u17fa" +
|
||||
"\0\u1838\0\u1876\0\u18b4\0\u03a2\0\u03a2\0\u03a2\0\u03a2\0\u03a2" +
|
||||
"\0\u18f2\0\u08b8\0\u08b8\0\u08b8\0\u03a2\0\u1930\0\u03a2\0\u196e" +
|
||||
"\0\u19ac\0\u19ea\0\u1a28\0\u1a66\0\u1aa4\0\u1ae2\0\u1b20\0\u1b5e" +
|
||||
"\0\u1b9c\0\u1bda\0\u11ae\0\u1c18\0\u0554\0\u0fbe\0\u1c56\0\u1c94" +
|
||||
"\0\u1cd2";
|
||||
"\0\0\0\72\0\164\0\256\0\350\0\u0122\0\u015c\0\u0196" +
|
||||
"\0\u01d0\0\u020a\0\u0244\0\u027e\0\u02b8\0\u02f2\0\u032c\0\u0366" +
|
||||
"\0\u0366\0\u03a0\0\u03da\0\u0414\0\u044e\0\u0488\0\u04c2\0\u04fc" +
|
||||
"\0\u0536\0\u0570\0\u05aa\0\u0366\0\u05e4\0\u061e\0\u0658\0\u0366" +
|
||||
"\0\u0692\0\u06cc\0\u0706\0\u0740\0\u077a\0\u07b4\0\u07ee\0\u0828" +
|
||||
"\0\u0862\0\u089c\0\u08d6\0\u0910\0\u094a\0\u0984\0\u09be\0\u09f8" +
|
||||
"\0\u0a32\0\u0366\0\u0366\0\u0366\0\u0366\0\u0366\0\u0366\0\u0366" +
|
||||
"\0\u0366\0\u0366\0\u0366\0\u0a6c\0\u0aa6\0\u0ae0\0\u0366\0\u0b1a" +
|
||||
"\0\u0b54\0\u0366\0\u0366\0\u0366\0\u0366\0\u0b8e\0\u0366\0\u0366" +
|
||||
"\0\u0366\0\u0366\0\u0bc8\0\u0c02\0\u0c3c\0\u0c76\0\u0cb0\0\u0366" +
|
||||
"\0\u0cea\0\u0d24\0\u0d24\0\u0d5e\0\u0d98\0\u0dd2\0\u0e0c\0\u0e46" +
|
||||
"\0\u0e46\0\u0366\0\u0e80\0\u0eba\0\u0ef4\0\u0f2e\0\u0f68\0\u0f68" +
|
||||
"\0\u0366\0\u0fa2\0\u0fdc\0\u0e46\0\u1016\0\u1050\0\u108a\0\u10c4" +
|
||||
"\0\u10fe\0\u1138\0\u1172\0\u11ac\0\u11e6\0\u1220\0\u0366\0\u0366" +
|
||||
"\0\u0366\0\u0828\0\u0828\0\u0828\0\u125a\0\u0828\0\u08d6\0\u1294" +
|
||||
"\0\u094a\0\u0984\0\u09be\0\u12ce\0\u0366\0\u09f8\0\u1308\0\u0a32" +
|
||||
"\0\u1342\0\u0828\0\u137c\0\u0366\0\u0366\0\u0366\0\u0366\0\u0366" +
|
||||
"\0\u0366\0\u0366\0\u0366\0\u13b6\0\u13f0\0\u142a\0\u1464\0\u149e" +
|
||||
"\0\u14d8\0\u1512\0\u154c\0\u1586\0\u15c0\0\u15fa\0\u1634\0\u166e" +
|
||||
"\0\u16a8\0\u16e2\0\u0366\0\u0366\0\u0366\0\u0366\0\u0366\0\u171c" +
|
||||
"\0\u0828\0\u0828\0\u0828\0\u0366\0\u1756\0\u0366\0\u1790\0\u17ca" +
|
||||
"\0\u1804\0\u183e\0\u1878\0\u18b2\0\u18ec\0\u1926\0\u1960\0\u199a" +
|
||||
"\0\u19d4\0\u108a\0\u1a0e\0\u04fc\0\u0eba\0\u1a48\0\u1a82\0\u1abc";
|
||||
|
||||
private static int[] zzUnpackRowMap() {
|
||||
int[] result = new int[185];
|
||||
int[] result = new int[184];
|
||||
int offset = 0;
|
||||
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -289,152 +288,146 @@ public class _M68kLexer implements FlexLexer {
|
||||
private static final String ZZ_TRANS_PACKED_0 =
|
||||
"\1\20\2\21\1\22\1\23\1\24\1\20\1\24\1\20" +
|
||||
"\2\24\2\20\5\24\1\20\1\25\1\20\5\24\1\26" +
|
||||
"\1\20\4\24\2\20\3\24\1\20\2\24\7\20\1\26" +
|
||||
"\7\20\1\26\3\20\3\24\1\20\2\21\1\22\1\27" +
|
||||
"\1\30\1\20\1\30\1\20\1\30\1\31\2\20\5\30" +
|
||||
"\1\20\1\32\1\20\1\33\4\30\1\26\1\20\4\30" +
|
||||
"\2\20\3\30\1\20\2\30\7\20\1\26\7\20\1\26" +
|
||||
"\3\20\3\30\1\20\2\34\1\35\1\27\1\36\1\20" +
|
||||
"\1\36\1\20\1\36\1\37\1\20\1\40\5\36\3\20" +
|
||||
"\5\36\1\41\1\20\4\36\2\20\3\36\1\20\2\36" +
|
||||
"\23\20\3\36\1\20\2\34\1\35\1\42\16\20\1\43" +
|
||||
"\6\20\1\41\44\20\2\34\1\35\1\44\1\45\1\46" +
|
||||
"\1\47\1\46\2\50\2\20\2\50\1\51\1\52\1\50" +
|
||||
"\1\20\1\50\1\53\1\50\1\54\3\50\1\41\1\20" +
|
||||
"\1\50\1\52\2\50\1\55\1\46\1\45\1\47\1\50" +
|
||||
"\1\46\1\50\1\54\1\56\1\57\1\60\1\61\2\20" +
|
||||
"\1\62\1\63\1\64\1\65\1\66\1\67\1\70\1\71" +
|
||||
"\1\72\1\73\3\20\1\74\1\75\1\50\1\20\2\34" +
|
||||
"\1\35\1\44\15\20\1\76\1\43\6\20\1\41\5\20" +
|
||||
"\1\77\13\20\1\100\1\101\1\102\1\20\1\103\1\104" +
|
||||
"\1\105\1\106\1\107\1\110\1\111\1\112\1\113\1\114" +
|
||||
"\1\115\4\20\2\34\1\35\1\27\7\20\1\40\1\116" +
|
||||
"\2\20\1\117\1\20\1\120\7\20\1\41\2\20\1\117" +
|
||||
"\10\20\1\116\30\20\2\34\1\35\1\44\1\121\1\46" +
|
||||
"\1\121\1\46\2\121\2\20\5\121\1\20\1\121\1\53" +
|
||||
"\5\121\1\41\1\20\4\121\1\55\1\46\3\121\1\46" +
|
||||
"\2\121\1\56\1\57\1\60\1\61\2\20\1\62\1\20" +
|
||||
"\1\20\4\24\2\20\1\24\10\20\1\26\7\20\1\26" +
|
||||
"\3\20\3\24\1\20\2\21\1\22\1\27\1\30\1\20" +
|
||||
"\1\30\1\20\1\30\1\31\2\20\5\30\1\20\1\32" +
|
||||
"\1\20\1\33\4\30\1\26\1\20\4\30\2\20\1\30" +
|
||||
"\10\20\1\26\7\20\1\26\3\20\3\30\1\20\2\34" +
|
||||
"\1\35\1\27\1\36\1\20\1\36\1\20\1\36\1\37" +
|
||||
"\1\20\1\40\5\36\3\20\5\36\1\41\1\20\4\36" +
|
||||
"\2\20\1\36\24\20\3\36\1\20\2\34\1\35\1\42" +
|
||||
"\16\20\1\43\6\20\1\41\40\20\2\34\1\35\1\44" +
|
||||
"\1\45\1\46\1\47\1\46\2\50\2\20\2\50\1\51" +
|
||||
"\1\52\1\50\1\20\1\50\1\53\1\50\1\54\3\50" +
|
||||
"\1\41\1\20\1\50\1\52\2\50\1\55\1\46\1\50" +
|
||||
"\1\46\1\56\1\57\1\60\1\61\2\20\1\62\1\63" +
|
||||
"\1\64\1\65\1\66\1\67\1\70\1\71\1\72\1\73" +
|
||||
"\3\20\3\121\1\20\2\34\1\35\1\44\15\20\1\76" +
|
||||
"\7\20\1\41\5\20\1\77\13\20\1\100\1\101\1\102" +
|
||||
"\1\20\1\103\1\104\1\105\1\106\1\107\1\110\1\111" +
|
||||
"\1\112\1\113\1\114\1\115\3\20\1\122\1\123\1\34" +
|
||||
"\1\35\1\44\25\122\1\41\16\122\1\124\1\125\1\126" +
|
||||
"\1\127\1\122\1\62\17\122\1\130\1\131\1\34\1\35" +
|
||||
"\72\130\1\20\2\132\1\133\1\27\1\134\1\20\1\134" +
|
||||
"\1\20\2\134\2\20\5\134\3\20\1\135\4\134\1\136" +
|
||||
"\1\20\4\134\2\20\3\134\1\20\2\134\23\20\3\134" +
|
||||
"\1\137\1\140\1\141\1\142\1\143\25\137\1\136\43\137" +
|
||||
"\1\20\2\34\1\35\1\27\25\20\1\41\43\20\1\130" +
|
||||
"\1\144\1\141\1\142\72\130\100\0\1\21\77\0\1\23" +
|
||||
"\75\0\1\145\7\24\1\146\5\24\1\147\1\0\1\150" +
|
||||
"\5\24\2\0\4\24\1\0\7\24\23\0\3\24\5\0" +
|
||||
"\1\151\1\0\1\151\1\0\2\151\2\0\5\151\3\0" +
|
||||
"\5\151\2\0\4\151\2\0\3\151\1\0\2\151\23\0" +
|
||||
"\3\151\1\26\3\0\72\26\4\0\1\27\76\0\1\30" +
|
||||
"\3\20\1\74\1\75\1\50\1\20\2\34\1\35\1\44" +
|
||||
"\15\20\1\76\1\43\6\20\1\41\5\20\1\77\7\20" +
|
||||
"\1\100\1\101\1\102\1\20\1\103\1\104\1\105\1\106" +
|
||||
"\1\107\1\110\1\111\1\112\1\113\1\114\1\115\4\20" +
|
||||
"\2\34\1\35\1\27\7\20\1\40\1\116\2\20\1\117" +
|
||||
"\1\20\1\120\7\20\1\41\2\20\1\117\35\20\2\34" +
|
||||
"\1\35\1\44\1\121\1\46\1\121\1\46\2\121\2\20" +
|
||||
"\5\121\1\20\1\121\1\53\5\121\1\41\1\20\4\121" +
|
||||
"\1\55\1\46\1\121\1\46\1\56\1\57\1\60\1\61" +
|
||||
"\2\20\1\62\1\20\1\64\1\65\1\66\1\67\1\70" +
|
||||
"\1\71\1\72\1\73\3\20\3\121\1\20\2\34\1\35" +
|
||||
"\1\44\15\20\1\76\7\20\1\41\5\20\1\77\7\20" +
|
||||
"\1\100\1\101\1\102\1\20\1\103\1\104\1\105\1\106" +
|
||||
"\1\107\1\110\1\111\1\112\1\113\1\114\1\115\3\20" +
|
||||
"\1\122\1\123\1\34\1\35\1\44\25\122\1\41\12\122" +
|
||||
"\1\124\1\125\1\126\1\127\1\122\1\62\17\122\1\130" +
|
||||
"\1\131\1\34\1\35\66\130\1\20\2\132\1\133\1\27" +
|
||||
"\1\134\1\20\1\134\1\20\2\134\1\20\1\40\5\134" +
|
||||
"\3\20\1\135\4\134\1\136\1\20\4\134\2\20\1\134" +
|
||||
"\24\20\3\134\1\137\1\140\1\141\1\142\1\143\25\137" +
|
||||
"\1\136\37\137\1\20\2\34\1\35\1\27\25\20\1\41" +
|
||||
"\37\20\1\130\1\144\1\141\1\142\66\130\74\0\1\21" +
|
||||
"\73\0\1\23\71\0\1\145\7\24\1\146\5\24\1\147" +
|
||||
"\1\0\1\150\5\24\2\0\4\24\1\0\3\24\23\0" +
|
||||
"\3\24\5\0\1\151\1\0\1\151\1\0\2\151\2\0" +
|
||||
"\5\151\3\0\5\151\2\0\4\151\2\0\1\151\24\0" +
|
||||
"\3\151\1\26\3\0\66\26\4\0\1\27\72\0\1\30" +
|
||||
"\1\31\1\30\1\31\1\30\2\31\1\152\5\30\1\0" +
|
||||
"\1\153\1\154\5\30\2\0\4\30\1\0\1\31\3\30" +
|
||||
"\1\31\2\30\23\0\3\30\5\0\7\31\1\152\5\31" +
|
||||
"\2\0\1\154\5\31\2\0\4\31\1\0\7\31\23\0" +
|
||||
"\3\31\5\0\1\155\1\0\1\155\1\0\2\155\2\0" +
|
||||
"\5\155\3\0\5\155\2\0\4\155\2\0\3\155\1\0" +
|
||||
"\2\155\23\0\3\155\5\0\1\156\1\31\1\30\1\31" +
|
||||
"\1\30\2\31\1\152\5\30\1\0\1\153\1\154\5\30" +
|
||||
"\2\0\4\30\1\0\1\31\1\156\2\30\1\31\2\30" +
|
||||
"\23\0\3\30\2\0\1\34\100\0\1\36\1\37\1\36" +
|
||||
"\1\37\1\36\2\37\1\0\5\36\1\0\1\153\1\0" +
|
||||
"\5\36\2\0\4\36\1\0\1\37\3\36\1\37\2\36" +
|
||||
"\23\0\3\36\5\0\7\37\1\0\5\37\3\0\5\37" +
|
||||
"\2\0\4\37\1\0\7\37\23\0\3\37\1\41\3\0" +
|
||||
"\72\41\4\0\1\42\125\0\2\157\1\160\1\161\42\0" +
|
||||
"\1\44\76\0\1\50\1\162\1\50\1\163\3\50\1\0" +
|
||||
"\5\50\2\0\6\50\2\0\4\50\1\0\1\162\6\50" +
|
||||
"\23\0\3\50\6\0\1\46\1\0\1\46\30\0\1\46" +
|
||||
"\3\0\1\46\35\0\1\50\1\164\1\50\1\164\3\50" +
|
||||
"\1\0\5\50\2\0\6\50\2\0\4\50\1\0\1\164" +
|
||||
"\6\50\23\0\3\50\5\0\7\50\1\0\5\50\2\0" +
|
||||
"\6\50\2\0\4\50\1\0\7\50\23\0\3\50\5\0" +
|
||||
"\7\50\1\0\3\50\1\165\1\50\2\0\6\50\2\0" +
|
||||
"\1\50\1\165\2\50\1\0\7\50\23\0\3\50\5\0" +
|
||||
"\7\50\1\0\5\50\2\0\3\50\1\166\2\50\2\0" +
|
||||
"\4\50\1\0\7\50\23\0\1\163\2\50\6\0\1\167" +
|
||||
"\1\0\1\167\23\0\1\167\4\0\7\167\33\0\7\50" +
|
||||
"\1\0\5\50\2\0\2\50\1\170\3\50\2\0\4\50" +
|
||||
"\1\0\6\50\1\170\23\0\3\50\41\0\1\171\42\0" +
|
||||
"\1\172\1\0\1\172\30\0\1\172\34\0\2\173\2\0" +
|
||||
"\27\173\1\174\15\173\1\175\24\173\2\176\2\0\27\176" +
|
||||
"\1\177\16\176\1\175\23\176\2\200\2\0\27\200\1\201" +
|
||||
"\17\200\1\175\22\200\5\0\7\50\1\0\5\50\2\0" +
|
||||
"\2\50\1\202\3\50\2\0\4\50\1\0\6\50\1\202" +
|
||||
"\23\0\3\50\5\0\7\50\1\0\5\50\2\0\6\50" +
|
||||
"\2\0\1\203\3\50\1\0\7\50\23\0\2\50\1\203" +
|
||||
"\22\0\1\204\75\0\1\205\31\0\1\206\1\207\42\0" +
|
||||
"\1\210\32\0\1\211\42\0\1\207\143\0\1\212\76\0" +
|
||||
"\1\213\76\0\1\77\21\0\1\214\74\0\1\215\30\0" +
|
||||
"\1\215\34\0\7\121\1\0\5\121\1\0\7\121\1\0" +
|
||||
"\5\121\1\0\7\121\23\0\3\121\2\122\3\0\25\122" +
|
||||
"\1\0\23\122\1\0\17\122\2\124\2\0\1\216\25\124" +
|
||||
"\1\216\1\217\15\124\1\122\4\124\1\216\17\124\2\125" +
|
||||
"\2\0\1\220\25\125\1\220\1\221\16\125\1\122\3\125" +
|
||||
"\1\220\17\125\2\126\2\0\1\222\25\126\1\222\1\223" +
|
||||
"\17\126\1\122\2\126\1\222\17\126\2\127\2\0\1\224" +
|
||||
"\25\127\1\224\1\225\21\127\1\122\1\224\17\127\2\130" +
|
||||
"\2\0\72\130\2\0\1\132\100\0\7\134\1\0\5\134" +
|
||||
"\3\0\5\134\2\0\4\134\1\0\7\134\23\0\3\134" +
|
||||
"\5\0\1\226\6\134\1\0\5\134\3\0\5\134\2\0" +
|
||||
"\4\134\1\0\1\134\1\226\5\134\23\0\3\134\1\136" +
|
||||
"\3\0\72\136\2\137\2\0\26\137\1\0\43\137\2\0" +
|
||||
"\1\141\73\0\2\137\2\0\1\143\10\137\1\227\14\137" +
|
||||
"\1\0\13\137\1\227\27\137\4\0\1\145\10\0\1\230" +
|
||||
"\2\0\1\231\1\0\1\147\2\0\1\232\7\0\1\231" +
|
||||
"\10\0\1\230\33\0\1\233\7\0\1\234\5\0\1\147" +
|
||||
"\57\0\1\147\105\0\1\235\66\0\7\151\1\235\5\151" +
|
||||
"\3\0\5\151\2\0\4\151\1\0\7\151\23\0\3\151" +
|
||||
"\14\0\1\236\61\0\1\237\3\0\72\237\14\0\1\240" +
|
||||
"\66\0\7\155\1\240\5\155\3\0\5\155\2\0\4\155" +
|
||||
"\1\0\7\155\23\0\3\155\5\0\1\30\1\31\1\30" +
|
||||
"\1\31\1\30\2\31\1\152\5\30\1\0\1\153\1\154" +
|
||||
"\1\30\1\241\3\30\2\0\4\30\1\0\1\31\3\30" +
|
||||
"\1\31\1\30\1\241\23\0\3\30\5\0\7\50\1\0" +
|
||||
"\5\50\2\0\6\50\2\0\4\50\1\0\7\50\23\0" +
|
||||
"\1\242\2\50\5\0\7\50\1\0\5\50\2\0\3\50" +
|
||||
"\1\243\2\50\2\0\4\50\1\0\7\50\23\0\3\50" +
|
||||
"\1\173\3\0\72\173\1\176\3\0\72\176\1\200\3\0" +
|
||||
"\72\200\5\0\7\50\1\0\5\50\2\0\3\50\1\244" +
|
||||
"\2\50\2\0\4\50\1\0\7\50\23\0\3\50\17\0" +
|
||||
"\1\245\77\0\1\245\54\0\2\216\2\0\27\216\1\246" +
|
||||
"\15\216\1\247\24\216\1\124\1\122\2\0\1\216\25\124" +
|
||||
"\1\216\23\124\1\216\17\124\2\220\2\0\27\220\1\250" +
|
||||
"\16\220\1\247\23\220\1\125\1\122\2\0\1\220\25\125" +
|
||||
"\1\220\23\125\1\220\17\125\2\222\2\0\27\222\1\251" +
|
||||
"\17\222\1\247\22\222\1\126\1\122\2\0\1\222\25\126" +
|
||||
"\1\222\23\126\1\222\17\126\2\224\2\0\27\224\1\252" +
|
||||
"\21\224\1\247\20\224\1\127\1\122\2\0\1\224\25\127" +
|
||||
"\1\224\23\127\1\224\17\127\5\0\7\134\1\0\5\134" +
|
||||
"\3\0\1\134\1\253\3\134\2\0\4\134\1\0\6\134" +
|
||||
"\1\253\23\0\3\134\2\137\2\0\25\137\1\254\1\0" +
|
||||
"\43\137\16\0\1\255\74\0\1\256\30\0\1\256\34\0" +
|
||||
"\1\257\34\0\1\257\37\0\1\233\10\0\1\230\2\0" +
|
||||
"\1\231\1\0\1\147\12\0\1\231\10\0\1\230\34\0" +
|
||||
"\1\30\1\31\1\30\1\31\1\30\2\31\1\152\5\30" +
|
||||
"\1\0\1\153\1\154\2\30\1\260\2\30\2\0\4\30" +
|
||||
"\1\0\1\31\3\30\1\31\2\30\23\0\3\30\1\216" +
|
||||
"\3\0\72\216\1\220\3\0\72\220\1\222\3\0\72\222" +
|
||||
"\1\224\3\0\72\224\5\0\7\134\1\0\5\134\3\0" +
|
||||
"\2\134\1\261\2\134\2\0\4\134\1\0\7\134\23\0" +
|
||||
"\3\134\2\137\2\0\3\137\1\262\22\137\1\0\10\137" +
|
||||
"\1\262\32\137\17\0\1\263\77\0\1\263\102\0\1\264" +
|
||||
"\20\0\1\264\33\0\1\30\1\31\1\30\1\31\1\30" +
|
||||
"\2\31\1\152\5\30\1\0\1\153\1\154\3\30\1\265" +
|
||||
"\1\30\2\0\4\30\1\0\1\31\3\30\1\31\2\30" +
|
||||
"\23\0\3\30\5\0\7\134\1\0\5\134\3\0\3\134" +
|
||||
"\1\266\1\134\2\0\4\134\1\0\7\134\23\0\3\134" +
|
||||
"\2\137\2\0\21\137\1\267\4\137\1\0\43\137\27\0" +
|
||||
"\1\270\46\0\2\267\2\0\26\267\1\0\43\267\30\0" +
|
||||
"\1\271\51\0\1\271\71\0";
|
||||
"\1\153\1\154\5\30\2\0\4\30\1\0\1\31\1\30" +
|
||||
"\1\31\23\0\3\30\5\0\7\31\1\152\5\31\2\0" +
|
||||
"\1\154\5\31\2\0\4\31\1\0\3\31\23\0\3\31" +
|
||||
"\5\0\1\155\1\0\1\155\1\0\2\155\2\0\5\155" +
|
||||
"\3\0\5\155\2\0\4\155\2\0\1\155\24\0\3\155" +
|
||||
"\5\0\1\156\1\31\1\30\1\31\1\30\2\31\1\152" +
|
||||
"\5\30\1\0\1\153\1\154\5\30\2\0\4\30\1\0" +
|
||||
"\1\31\1\30\1\31\23\0\3\30\2\0\1\34\74\0" +
|
||||
"\1\36\1\37\1\36\1\37\1\36\2\37\1\0\5\36" +
|
||||
"\1\0\1\153\1\0\5\36\2\0\4\36\1\0\1\37" +
|
||||
"\1\36\1\37\23\0\3\36\5\0\7\37\1\0\5\37" +
|
||||
"\3\0\5\37\2\0\4\37\1\0\3\37\23\0\3\37" +
|
||||
"\1\41\3\0\66\41\4\0\1\42\121\0\2\157\1\160" +
|
||||
"\1\161\36\0\1\44\72\0\1\50\1\162\1\50\1\163" +
|
||||
"\3\50\1\0\5\50\2\0\6\50\2\0\4\50\1\0" +
|
||||
"\1\162\2\50\23\0\3\50\6\0\1\46\1\0\1\46" +
|
||||
"\30\0\1\46\1\0\1\46\33\0\1\50\1\164\1\50" +
|
||||
"\1\164\3\50\1\0\5\50\2\0\6\50\2\0\4\50" +
|
||||
"\1\0\1\164\2\50\23\0\3\50\5\0\7\50\1\0" +
|
||||
"\5\50\2\0\6\50\2\0\4\50\1\0\3\50\23\0" +
|
||||
"\3\50\5\0\7\50\1\0\3\50\1\165\1\50\2\0" +
|
||||
"\6\50\2\0\1\50\1\165\2\50\1\0\3\50\23\0" +
|
||||
"\3\50\5\0\7\50\1\0\5\50\2\0\3\50\1\166" +
|
||||
"\2\50\2\0\4\50\1\0\3\50\23\0\1\163\2\50" +
|
||||
"\5\0\4\167\4\0\1\167\10\0\1\167\5\0\1\167" +
|
||||
"\4\0\3\167\25\0\1\167\5\0\7\50\1\0\5\50" +
|
||||
"\2\0\2\50\1\170\3\50\2\0\4\50\1\0\3\50" +
|
||||
"\23\0\3\50\41\0\1\171\36\0\1\172\1\0\1\172" +
|
||||
"\30\0\1\172\30\0\2\173\2\0\27\173\1\174\11\173" +
|
||||
"\1\175\24\173\2\176\2\0\27\176\1\177\12\176\1\175" +
|
||||
"\23\176\2\200\2\0\27\200\1\201\13\200\1\175\22\200" +
|
||||
"\5\0\7\50\1\0\5\50\2\0\2\50\1\202\3\50" +
|
||||
"\2\0\4\50\1\0\3\50\23\0\3\50\5\0\7\50" +
|
||||
"\1\0\5\50\2\0\6\50\2\0\1\203\3\50\1\0" +
|
||||
"\3\50\23\0\2\50\1\203\22\0\1\204\71\0\1\205" +
|
||||
"\25\0\1\206\1\207\42\0\1\210\26\0\1\211\42\0" +
|
||||
"\1\207\133\0\1\212\72\0\1\213\72\0\1\77\21\0" +
|
||||
"\1\214\70\0\1\215\61\0\7\121\1\0\5\121\1\0" +
|
||||
"\7\121\1\0\5\121\1\0\3\121\23\0\3\121\2\122" +
|
||||
"\3\0\25\122\1\0\17\122\1\0\17\122\2\124\2\0" +
|
||||
"\1\216\25\124\1\216\1\217\11\124\1\122\4\124\1\216" +
|
||||
"\17\124\2\125\2\0\1\220\25\125\1\220\1\221\12\125" +
|
||||
"\1\122\3\125\1\220\17\125\2\126\2\0\1\222\25\126" +
|
||||
"\1\222\1\223\13\126\1\122\2\126\1\222\17\126\2\127" +
|
||||
"\2\0\1\224\25\127\1\224\1\225\15\127\1\122\1\224" +
|
||||
"\17\127\2\130\2\0\66\130\2\0\1\132\74\0\7\134" +
|
||||
"\1\0\5\134\3\0\5\134\2\0\4\134\1\0\3\134" +
|
||||
"\23\0\3\134\5\0\1\226\6\134\1\0\5\134\3\0" +
|
||||
"\5\134\2\0\4\134\1\0\3\134\23\0\3\134\1\136" +
|
||||
"\3\0\66\136\2\137\2\0\26\137\1\0\37\137\2\0" +
|
||||
"\1\141\67\0\2\137\2\0\1\143\10\137\1\227\14\137" +
|
||||
"\1\0\37\137\4\0\1\145\10\0\1\230\2\0\1\231" +
|
||||
"\1\0\1\147\2\0\1\232\7\0\1\231\40\0\1\145" +
|
||||
"\7\0\1\233\5\0\1\147\2\0\1\232\50\0\1\147" +
|
||||
"\101\0\1\234\62\0\7\151\1\234\5\151\3\0\5\151" +
|
||||
"\2\0\4\151\1\0\3\151\23\0\3\151\14\0\1\235" +
|
||||
"\55\0\1\236\3\0\66\236\14\0\1\237\62\0\7\155" +
|
||||
"\1\237\5\155\3\0\5\155\2\0\4\155\1\0\3\155" +
|
||||
"\23\0\3\155\5\0\1\30\1\31\1\30\1\31\1\30" +
|
||||
"\2\31\1\152\5\30\1\0\1\153\1\154\1\30\1\240" +
|
||||
"\3\30\2\0\4\30\1\0\1\31\1\30\1\31\23\0" +
|
||||
"\3\30\5\0\7\50\1\0\5\50\2\0\6\50\2\0" +
|
||||
"\4\50\1\0\3\50\23\0\1\241\2\50\5\0\7\50" +
|
||||
"\1\0\5\50\2\0\3\50\1\242\2\50\2\0\4\50" +
|
||||
"\1\0\3\50\23\0\3\50\1\173\3\0\66\173\1\176" +
|
||||
"\3\0\66\176\1\200\3\0\66\200\5\0\7\50\1\0" +
|
||||
"\5\50\2\0\3\50\1\243\2\50\2\0\4\50\1\0" +
|
||||
"\3\50\23\0\3\50\17\0\1\244\73\0\1\244\50\0" +
|
||||
"\2\216\2\0\27\216\1\245\11\216\1\246\24\216\1\124" +
|
||||
"\1\122\2\0\1\216\25\124\1\216\17\124\1\216\17\124" +
|
||||
"\2\220\2\0\27\220\1\247\12\220\1\246\23\220\1\125" +
|
||||
"\1\122\2\0\1\220\25\125\1\220\17\125\1\220\17\125" +
|
||||
"\2\222\2\0\27\222\1\250\13\222\1\246\22\222\1\126" +
|
||||
"\1\122\2\0\1\222\25\126\1\222\17\126\1\222\17\126" +
|
||||
"\2\224\2\0\27\224\1\251\15\224\1\246\20\224\1\127" +
|
||||
"\1\122\2\0\1\224\25\127\1\224\17\127\1\224\17\127" +
|
||||
"\5\0\7\134\1\0\5\134\3\0\1\134\1\252\3\134" +
|
||||
"\2\0\4\134\1\0\3\134\23\0\3\134\2\137\2\0" +
|
||||
"\25\137\1\253\1\0\37\137\16\0\1\254\70\0\1\255" +
|
||||
"\61\0\1\256\71\0\1\30\1\31\1\30\1\31\1\30" +
|
||||
"\2\31\1\152\5\30\1\0\1\153\1\154\2\30\1\257" +
|
||||
"\2\30\2\0\4\30\1\0\1\31\1\30\1\31\23\0" +
|
||||
"\3\30\1\216\3\0\66\216\1\220\3\0\66\220\1\222" +
|
||||
"\3\0\66\222\1\224\3\0\66\224\5\0\7\134\1\0" +
|
||||
"\5\134\3\0\2\134\1\260\2\134\2\0\4\134\1\0" +
|
||||
"\3\134\23\0\3\134\2\137\2\0\3\137\1\261\22\137" +
|
||||
"\1\0\37\137\17\0\1\262\73\0\1\262\76\0\1\263" +
|
||||
"\50\0\1\30\1\31\1\30\1\31\1\30\2\31\1\152" +
|
||||
"\5\30\1\0\1\153\1\154\3\30\1\264\1\30\2\0" +
|
||||
"\4\30\1\0\1\31\1\30\1\31\23\0\3\30\5\0" +
|
||||
"\7\134\1\0\5\134\3\0\3\134\1\265\1\134\2\0" +
|
||||
"\4\134\1\0\3\134\23\0\3\134\2\137\2\0\21\137" +
|
||||
"\1\266\4\137\1\0\37\137\27\0\1\267\42\0\2\266" +
|
||||
"\2\0\26\266\1\0\37\266\30\0\1\270\45\0\1\270" +
|
||||
"\65\0";
|
||||
|
||||
private static int[] zzUnpackTrans() {
|
||||
int[] result = new int[7440];
|
||||
int[] result = new int[6902];
|
||||
int offset = 0;
|
||||
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -477,11 +470,11 @@ public class _M68kLexer implements FlexLexer {
|
||||
"\11\1\1\11\6\1\1\11\3\1\1\0\5\1\3\0" +
|
||||
"\1\1\3\11\11\1\2\0\1\11\4\0\2\1\10\11" +
|
||||
"\3\0\1\1\1\0\1\1\1\0\1\1\1\0\3\1" +
|
||||
"\4\0\5\11\4\1\1\11\1\0\1\11\3\0\2\1" +
|
||||
"\3\0\5\11\4\1\1\11\1\0\1\11\3\0\2\1" +
|
||||
"\3\0\3\1\2\0\3\1\1\0\1\1";
|
||||
|
||||
private static int[] zzUnpackAttribute() {
|
||||
int[] result = new int[185];
|
||||
int[] result = new int[184];
|
||||
int offset = 0;
|
||||
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
|
||||
return result;
|
||||
|
||||
@@ -211,7 +211,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean AddressRegisterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode")) return false;
|
||||
if (!nextTokenIsFast(b, ROUND_L)) return false;
|
||||
@@ -221,8 +221,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
||||
r = r && AddressRegister(b, l + 1);
|
||||
r = r && consumeToken(b, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && AddressRegisterIndirectWithIndexNewAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@@ -246,15 +245,8 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean AddressRegisterIndirectWithIndexNewAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexNewAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// expr? ROUND_L AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// expr? ROUND_L AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean AddressRegisterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode")) return false;
|
||||
boolean r;
|
||||
@@ -263,8 +255,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
r = r && consumeToken(b, ROUND_L);
|
||||
r = r && AddressRegister(b, l + 1);
|
||||
r = r && consumeToken(b, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && AddressRegisterIndirectWithIndexOldAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@@ -277,13 +268,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean AddressRegisterIndirectWithIndexOldAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AddressRegisterIndirectWithIndexOldAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// OPSIZE_W|OPSIZE_L
|
||||
public static boolean AddressSize(PsiBuilder b, int l) {
|
||||
@@ -364,12 +348,12 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
// MNEMONIC OperandSize?
|
||||
public static boolean AsmOp(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "AsmOp")) return false;
|
||||
if (!nextTokenIs(b, MNEMONIC)) return false;
|
||||
if (!nextTokenIs(b, "<mnemonic>", MNEMONIC)) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
Marker m = enter_section_(b, l, _NONE_, ASM_OP, "<mnemonic>");
|
||||
r = consumeToken(b, MNEMONIC);
|
||||
r = r && AsmOp_1(b, l + 1);
|
||||
exit_section_(b, m, ASM_OP, r);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -547,6 +531,25 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// DataOrAddressRegister DataWidth?
|
||||
public static boolean IndexRegister(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "IndexRegister")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NONE_, INDEX_REGISTER, "<index register>");
|
||||
r = DataOrAddressRegister(b, l + 1);
|
||||
r = r && IndexRegister_1(b, l + 1);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean IndexRegister_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "IndexRegister_1")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// AsmInstruction | MacroCall
|
||||
static boolean Instruction(PsiBuilder b, int l) {
|
||||
@@ -658,7 +661,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ((MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG
|
||||
// ((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;
|
||||
@@ -672,7 +675,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r || p;
|
||||
}
|
||||
|
||||
// (MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)
|
||||
// (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;
|
||||
@@ -683,17 +686,25 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// MacroNameDefinition MACRO_TAG
|
||||
// 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;
|
||||
@@ -930,7 +941,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// ROUND_L (expr SEPARATOR)? PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// ROUND_L (expr SEPARATOR)? PC SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean ProgramCounterIndirectWithIndexNewAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode")) return false;
|
||||
if (!nextTokenIsFast(b, ROUND_L)) return false;
|
||||
@@ -939,8 +950,7 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
r = consumeTokenFast(b, ROUND_L);
|
||||
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_1(b, l + 1);
|
||||
r = r && consumeTokens(b, 0, PC, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && ProgramCounterIndirectWithIndexNewAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@@ -964,23 +974,15 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean ProgramCounterIndirectWithIndexNewAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexNewAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// expr? ROUND_L PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
// expr? ROUND_L PC SEPARATOR IndexRegister ROUND_R
|
||||
public static boolean ProgramCounterIndirectWithIndexOldAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NONE_, PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE, "<AddressingMode>");
|
||||
r = ProgramCounterIndirectWithIndexOldAddressingMode_0(b, l + 1);
|
||||
r = r && consumeTokens(b, 0, ROUND_L, PC, SEPARATOR);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && ProgramCounterIndirectWithIndexOldAddressingMode_5(b, l + 1);
|
||||
r = r && IndexRegister(b, l + 1);
|
||||
r = r && consumeToken(b, ROUND_R);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
@@ -993,13 +995,6 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// DataWidth?
|
||||
private static boolean ProgramCounterIndirectWithIndexOldAddressingMode_5(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "ProgramCounterIndirectWithIndexOldAddressingMode_5")) return false;
|
||||
DataWidth(b, l + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// CURRENT_PC_SYMBOL
|
||||
public static boolean ProgramCounterReference(PsiBuilder b, int l) {
|
||||
@@ -1026,27 +1021,27 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// (DataOrAddressRegister|RegisterRange) ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
|
||||
// (RegisterRange|DataOrAddressRegister) (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
|
||||
public static boolean RegisterListAddressingMode(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NONE_, REGISTER_LIST_ADDRESSING_MODE, "<AddressingMode>");
|
||||
Marker m = enter_section_(b, l, _NONE_, REGISTER_LIST_ADDRESSING_MODE, "<register list>");
|
||||
r = RegisterListAddressingMode_0(b, l + 1);
|
||||
r = r && RegisterListAddressingMode_1(b, l + 1);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataOrAddressRegister|RegisterRange
|
||||
// RegisterRange|DataOrAddressRegister
|
||||
private static boolean RegisterListAddressingMode_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_0")) return false;
|
||||
boolean r;
|
||||
r = DataOrAddressRegister(b, l + 1);
|
||||
if (!r) r = RegisterRange(b, l + 1);
|
||||
r = RegisterRange(b, l + 1);
|
||||
if (!r) r = DataOrAddressRegister(b, l + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
// ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
|
||||
// (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
|
||||
private static boolean RegisterListAddressingMode_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1")) return false;
|
||||
while (true) {
|
||||
@@ -1057,44 +1052,71 @@ public class M68kParser implements PsiParser, LightPsiParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
// (OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange)
|
||||
// OP_AR_DIV (RegisterRange|DataOrAddressRegister)
|
||||
private static boolean RegisterListAddressingMode_1_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = RegisterListAddressingMode_1_0_0(b, l + 1);
|
||||
r = consumeTokenFast(b, OP_AR_DIV);
|
||||
r = r && RegisterListAddressingMode_1_0_1(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// OP_AR_DIV|OP_MINUS
|
||||
private static boolean RegisterListAddressingMode_1_0_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0_0")) return false;
|
||||
boolean r;
|
||||
r = consumeTokenFast(b, OP_AR_DIV);
|
||||
if (!r) r = consumeTokenFast(b, OP_MINUS);
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataOrAddressRegister|RegisterRange
|
||||
// RegisterRange|DataOrAddressRegister
|
||||
private static boolean RegisterListAddressingMode_1_0_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterListAddressingMode_1_0_1")) return false;
|
||||
boolean r;
|
||||
r = DataOrAddressRegister(b, l + 1);
|
||||
if (!r) r = RegisterRange(b, l + 1);
|
||||
r = RegisterRange(b, l + 1);
|
||||
if (!r) r = DataOrAddressRegister(b, l + 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* ********************************************************** */
|
||||
// DataOrAddressRegister OP_MINUS DataOrAddressRegister
|
||||
static boolean RegisterRange(PsiBuilder b, int l) {
|
||||
// (DataRegister OP_MINUS DataRegister) | (AddressRegister OP_MINUS AddressRegister) | (DataRegister OP_MINUS AddressRegister)
|
||||
public static boolean RegisterRange(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterRange")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b, l, _NONE_, REGISTER_RANGE, "<register range>");
|
||||
r = RegisterRange_0(b, l + 1);
|
||||
if (!r) r = RegisterRange_1(b, l + 1);
|
||||
if (!r) r = RegisterRange_2(b, l + 1);
|
||||
exit_section_(b, l, m, r, false, null);
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataRegister OP_MINUS DataRegister
|
||||
private static boolean RegisterRange_0(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterRange_0")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = DataOrAddressRegister(b, l + 1);
|
||||
r = DataRegister(b, l + 1);
|
||||
r = r && consumeToken(b, OP_MINUS);
|
||||
r = r && DataOrAddressRegister(b, l + 1);
|
||||
r = r && DataRegister(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// AddressRegister OP_MINUS AddressRegister
|
||||
private static boolean RegisterRange_1(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterRange_1")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = AddressRegister(b, l + 1);
|
||||
r = r && consumeToken(b, OP_MINUS);
|
||||
r = r && AddressRegister(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// DataRegister OP_MINUS AddressRegister
|
||||
private static boolean RegisterRange_2(PsiBuilder b, int l) {
|
||||
if (!recursion_guard_(b, l, "RegisterRange_2")) return false;
|
||||
boolean r;
|
||||
Marker m = enter_section_(b);
|
||||
r = DataRegister(b, l + 1);
|
||||
r = r && consumeToken(b, OP_MINUS);
|
||||
r = r && AddressRegister(b, l + 1);
|
||||
exit_section_(b, m, null, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface M68kAddressRegisterIndirectAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface M68kAddressRegisterIndirectPostIncAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectPostIncAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface M68kAddressRegisterIndirectPreDecAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectPreDecAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
+2
-2
@@ -3,12 +3,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface M68kAddressRegisterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
@NotNull
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,12 +3,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface M68kAddressRegisterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
@NotNull
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
+3
-6
@@ -4,18 +4,15 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement, M68kWithIndexRegister {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getDataWidth();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getRegister();
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
+3
-6
@@ -4,18 +4,15 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kAddressRegisterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithAddressRegisterIndirect, M68kWithDisplacement, M68kWithIndexRegister {
|
||||
|
||||
@NotNull
|
||||
M68kAddressRegister getAddressRegister();
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getDataWidth();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getRegister();
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kAsmOp extends M68kPsiElement {
|
||||
@@ -8,4 +9,9 @@ public interface M68kAsmOp extends M68kPsiElement {
|
||||
@Nullable
|
||||
M68kOperandSize getOperandSize();
|
||||
|
||||
@NotNull
|
||||
String getMnemonic();
|
||||
|
||||
int getOpSize();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kIndexRegister extends M68kPsiElement {
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getDataWidth();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getRegister();
|
||||
|
||||
boolean isLongWidth();
|
||||
|
||||
}
|
||||
@@ -3,4 +3,6 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
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;
|
||||
|
||||
public interface M68kProgramCounterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kProgramCounterIndirectWithDisplacementNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement {
|
||||
|
||||
@NotNull
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kProgramCounterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode {
|
||||
public interface M68kProgramCounterIndirectWithDisplacementOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement {
|
||||
|
||||
@Nullable
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
+3
-6
@@ -4,15 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode {
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getDataWidth();
|
||||
public interface M68kProgramCounterIndirectWithIndexNewAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
|
||||
|
||||
@NotNull
|
||||
M68kRegister getRegister();
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
+3
-6
@@ -4,15 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode {
|
||||
|
||||
@Nullable
|
||||
M68kDataWidth getDataWidth();
|
||||
public interface M68kProgramCounterIndirectWithIndexOldAddressingMode extends M68kAddressingMode, M68kWithDisplacement, M68kWithIndexRegister {
|
||||
|
||||
@NotNull
|
||||
M68kRegister getRegister();
|
||||
M68kIndexRegister getIndexRegister();
|
||||
|
||||
@Nullable
|
||||
M68kExpr getExpr();
|
||||
M68kExpr getDisplacement();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import de.platon42.intellij.plugins.m68k.asm.Register;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface M68kRegisterListAddressingMode extends M68kAddressingMode {
|
||||
|
||||
@NotNull
|
||||
List<M68kRegister> getRegisterList();
|
||||
|
||||
@NotNull
|
||||
List<M68kRegisterRange> getRegisterRangeList();
|
||||
|
||||
@NotNull
|
||||
Set<Register> getRegisters();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface M68kRegisterRange extends M68kPsiElement {
|
||||
|
||||
@NotNull
|
||||
List<M68kRegister> getRegisterList();
|
||||
|
||||
@NotNull
|
||||
M68kRegister getStartRegister();
|
||||
|
||||
@Nullable
|
||||
M68kRegister getEndRegister();
|
||||
|
||||
}
|
||||
@@ -48,6 +48,7 @@ public interface M68kTypes {
|
||||
IElementType EXPR = new M68kElementType("EXPR");
|
||||
IElementType GLOBAL_LABEL = M68kStubElementTypeFactory.stubFactory("GLOBAL_LABEL");
|
||||
IElementType IMMEDIATE_DATA = new M68kElementType("IMMEDIATE_DATA");
|
||||
IElementType INDEX_REGISTER = new M68kElementType("INDEX_REGISTER");
|
||||
IElementType LITERAL_EXPR = new M68kElementType("LITERAL_EXPR");
|
||||
IElementType LOCAL_LABEL = new M68kElementType("LOCAL_LABEL");
|
||||
IElementType MACRO_CALL = new M68kElementType("MACRO_CALL");
|
||||
@@ -65,6 +66,7 @@ public interface M68kTypes {
|
||||
IElementType REF_EXPR = new M68kElementType("REF_EXPR");
|
||||
IElementType REGISTER = new M68kElementType("REGISTER");
|
||||
IElementType REGISTER_LIST_ADDRESSING_MODE = new M68kElementType("REGISTER_LIST_ADDRESSING_MODE");
|
||||
IElementType REGISTER_RANGE = new M68kElementType("REGISTER_RANGE");
|
||||
IElementType SPECIAL_REGISTER = new M68kElementType("SPECIAL_REGISTER");
|
||||
IElementType SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE = new M68kElementType("SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE");
|
||||
IElementType STATEMENT = new M68kElementType("STATEMENT");
|
||||
@@ -211,6 +213,8 @@ public interface M68kTypes {
|
||||
return new M68kGlobalLabelImpl(node);
|
||||
} else if (type == IMMEDIATE_DATA) {
|
||||
return new M68kImmediateDataImpl(node);
|
||||
} else if (type == INDEX_REGISTER) {
|
||||
return new M68kIndexRegisterImpl(node);
|
||||
} else if (type == LITERAL_EXPR) {
|
||||
return new M68kLiteralExprImpl(node);
|
||||
} else if (type == LOCAL_LABEL) {
|
||||
@@ -243,6 +247,8 @@ public interface M68kTypes {
|
||||
return new M68kRefExprImpl(node);
|
||||
} else if (type == REGISTER_LIST_ADDRESSING_MODE) {
|
||||
return new M68kRegisterListAddressingModeImpl(node);
|
||||
} else if (type == REGISTER_RANGE) {
|
||||
return new M68kRegisterRangeImpl(node);
|
||||
} else if (type == SPECIAL_REGISTER) {
|
||||
return new M68kSpecialRegisterImpl(node);
|
||||
} else if (type == SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE) {
|
||||
|
||||
@@ -20,30 +20,43 @@ public class M68kVisitor extends PsiElementVisitor {
|
||||
|
||||
public void visitAddressRegisterIndirectAddressingMode(@NotNull M68kAddressRegisterIndirectAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
}
|
||||
|
||||
public void visitAddressRegisterIndirectPostIncAddressingMode(@NotNull M68kAddressRegisterIndirectPostIncAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
}
|
||||
|
||||
public void visitAddressRegisterIndirectPreDecAddressingMode(@NotNull M68kAddressRegisterIndirectPreDecAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
}
|
||||
|
||||
public void visitAddressRegisterIndirectWithDisplacementNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementNewAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
// visitWithDisplacement(o);
|
||||
}
|
||||
|
||||
public void visitAddressRegisterIndirectWithDisplacementOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithDisplacementOldAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
// visitWithDisplacement(o);
|
||||
}
|
||||
|
||||
public void visitAddressRegisterIndirectWithIndexNewAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexNewAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
// visitWithDisplacement(o);
|
||||
// visitWithIndexRegister(o);
|
||||
}
|
||||
|
||||
public void visitAddressRegisterIndirectWithIndexOldAddressingMode(@NotNull M68kAddressRegisterIndirectWithIndexOldAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithAddressRegisterIndirect(o);
|
||||
// visitWithDisplacement(o);
|
||||
// visitWithIndexRegister(o);
|
||||
}
|
||||
|
||||
public void visitAddressSize(@NotNull M68kAddressSize o) {
|
||||
@@ -86,6 +99,10 @@ public class M68kVisitor extends PsiElementVisitor {
|
||||
visitAddressingMode(o);
|
||||
}
|
||||
|
||||
public void visitIndexRegister(@NotNull M68kIndexRegister o) {
|
||||
visitPsiElement(o);
|
||||
}
|
||||
|
||||
public void visitLocalLabel(@NotNull M68kLocalLabel o) {
|
||||
visitNamedElement(o);
|
||||
}
|
||||
@@ -116,18 +133,24 @@ public class M68kVisitor extends PsiElementVisitor {
|
||||
|
||||
public void visitProgramCounterIndirectWithDisplacementNewAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementNewAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithDisplacement(o);
|
||||
}
|
||||
|
||||
public void visitProgramCounterIndirectWithDisplacementOldAddressingMode(@NotNull M68kProgramCounterIndirectWithDisplacementOldAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithDisplacement(o);
|
||||
}
|
||||
|
||||
public void visitProgramCounterIndirectWithIndexNewAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexNewAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithDisplacement(o);
|
||||
// visitWithIndexRegister(o);
|
||||
}
|
||||
|
||||
public void visitProgramCounterIndirectWithIndexOldAddressingMode(@NotNull M68kProgramCounterIndirectWithIndexOldAddressingMode o) {
|
||||
visitAddressingMode(o);
|
||||
// visitWithDisplacement(o);
|
||||
// visitWithIndexRegister(o);
|
||||
}
|
||||
|
||||
public void visitProgramCounterReference(@NotNull M68kProgramCounterReference o) {
|
||||
@@ -142,6 +165,10 @@ public class M68kVisitor extends PsiElementVisitor {
|
||||
visitAddressingMode(o);
|
||||
}
|
||||
|
||||
public void visitRegisterRange(@NotNull M68kRegisterRange o) {
|
||||
visitPsiElement(o);
|
||||
}
|
||||
|
||||
public void visitSpecialRegister(@NotNull M68kSpecialRegister o) {
|
||||
visitRegister(o);
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public class M68kAddressRegisterIndirectWithDisplacementNewAddressingModeImpl ex
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public class M68kAddressRegisterIndirectWithDisplacementOldAddressingModeImpl ex
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
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));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getDataWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
|
||||
+3
-9
@@ -31,21 +31,15 @@ public class M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl extends M
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kAddressRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getDataWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kAsmOp;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kPsiImplUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -33,4 +34,15 @@ public class M68kAsmOpImpl extends ASTWrapperPsiElement implements M68kAsmOp {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kOperandSize.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getMnemonic() {
|
||||
return M68kPsiImplUtil.getMnemonic(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpSize() {
|
||||
return M68kPsiImplUtil.getOpSize(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class M68kIndexRegisterImpl extends ASTWrapperPsiElement implements M68kIndexRegister {
|
||||
|
||||
public M68kIndexRegisterImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull M68kVisitor visitor) {
|
||||
visitor.visitIndexRegister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getDataWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongWidth() {
|
||||
return M68kPsiImplUtil.isLongWidth(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kOperandSize;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kPsiImplUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -24,4 +25,9 @@ public class M68kOperandSizeImpl extends ASTWrapperPsiElement implements M68kOpe
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return M68kPsiImplUtil.getSize(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ public class M68kProgramCounterIndirectWithDisplacementNewAddressingModeImpl ext
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kExpr.class));
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class M68kProgramCounterIndirectWithDisplacementOldAddressingModeImpl ext
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
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.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kExpr;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kIndexRegister;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kProgramCounterIndirectWithIndexNewAddressingMode;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -25,21 +28,15 @@ public class M68kProgramCounterIndirectWithIndexNewAddressingModeImpl extends M6
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getDataWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
|
||||
+7
-10
@@ -4,7 +4,10 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kExpr;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kIndexRegister;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kProgramCounterIndirectWithIndexOldAddressingMode;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -25,21 +28,15 @@ public class M68kProgramCounterIndirectWithIndexOldAddressingModeImpl extends M6
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kDataWidth getDataWidth() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kDataWidth.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kRegister.class));
|
||||
public M68kIndexRegister getIndexRegister() {
|
||||
return notNullChild(PsiTreeUtil.getChildOfType(this, M68kIndexRegister.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kExpr getExpr() {
|
||||
public M68kExpr getDisplacement() {
|
||||
return PsiTreeUtil.getChildOfType(this, M68kExpr.class);
|
||||
}
|
||||
|
||||
|
||||
+15
-3
@@ -4,12 +4,12 @@ package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegister;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterListAddressingMode;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import de.platon42.intellij.plugins.m68k.asm.Register;
|
||||
import de.platon42.intellij.plugins.m68k.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl implements M68kRegisterListAddressingMode {
|
||||
|
||||
@@ -34,4 +34,16 @@ public class M68kRegisterListAddressingModeImpl extends M68kAddressingModeImpl i
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegister.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<M68kRegisterRange> getRegisterRangeList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegisterRange.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Register> getRegisters() {
|
||||
return M68kPsiImplUtil.getRegisters(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package de.platon42.intellij.plugins.m68k.psi.impl;
|
||||
|
||||
import com.intellij.extapi.psi.ASTWrapperPsiElement;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegister;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterRange;
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class M68kRegisterRangeImpl extends ASTWrapperPsiElement implements M68kRegisterRange {
|
||||
|
||||
public M68kRegisterRangeImpl(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull M68kVisitor visitor) {
|
||||
visitor.visitRegisterRange(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof M68kVisitor) accept((M68kVisitor) visitor);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<M68kRegister> getRegisterList() {
|
||||
return PsiTreeUtil.getChildrenOfTypeAsList(this, M68kRegister.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public M68kRegister getStartRegister() {
|
||||
List<M68kRegister> p1 = getRegisterList();
|
||||
return p1.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public M68kRegister getEndRegister() {
|
||||
List<M68kRegister> p1 = getRegisterList();
|
||||
return p1.size() < 2 ? null : p1.get(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class M68kFileElementType private constructor() : ILightStubFileElementType<PsiF
|
||||
@JvmField
|
||||
val INSTANCE = M68kFileElementType()
|
||||
|
||||
const val STUB_VERSION = 4
|
||||
const val STUB_VERSION = 5
|
||||
const val STUB_EXTERNAL_ID_PREFIX = "MC68000."
|
||||
const val EXTERNAL_ID = STUB_EXTERNAL_ID_PREFIX + "FILE"
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ object AssemblerDirectives {
|
||||
"extern", "nref", "xdef", "xref", "globl", "public", "weak",
|
||||
|
||||
"reg", "equr", "equrl",
|
||||
"freg", "fequr", "fequrl",
|
||||
|
||||
"incdir", "include", "incbin", "output",
|
||||
|
||||
@@ -45,6 +46,13 @@ object AssemblerDirectives {
|
||||
"assert", "fail", "print", "printt", "printv", "echo",
|
||||
|
||||
"inline", "einline",
|
||||
"rem", "erem"
|
||||
"rem", "erem",
|
||||
|
||||
"machine", "mc68000", "mc68010", "mc68020", "mc68030", "mc68040", "mc68060",
|
||||
"fpu",
|
||||
|
||||
"basereg", "endb", "far", "near", "initnear",
|
||||
|
||||
"opt"
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package de.platon42.intellij.plugins.m68k.asm
|
||||
|
||||
const val CC_X_CLEAR = 0x10000
|
||||
const val CC_X_SET = 0x20000
|
||||
const val CC_X_UNDEF = 0x30000
|
||||
const val CC_X_RES = 0x40000
|
||||
const val CC_X_AND = 0x50000
|
||||
const val CC_X_OR = 0x60000
|
||||
const val CC_X_CARRY = 0x70000
|
||||
const val CC_X_TST = 0xf0000
|
||||
|
||||
const val CC_N_CLEAR = 0x01000
|
||||
const val CC_N_SET = 0x02000
|
||||
const val CC_N_UNDEF = 0x03000
|
||||
const val CC_N_RES = 0x04000
|
||||
const val CC_N_AND = 0x05000
|
||||
const val CC_N_OR = 0x06000
|
||||
const val CC_N_TST = 0x0f000
|
||||
|
||||
const val CC_Z_CLEAR = 0x00100
|
||||
const val CC_Z_SET = 0x00200
|
||||
const val CC_Z_UNDEF = 0x00300
|
||||
const val CC_Z_RES = 0x00400
|
||||
const val CC_Z_AND = 0x00500
|
||||
const val CC_Z_OR = 0x00600
|
||||
const val CC_Z_TST = 0x00f00
|
||||
|
||||
const val CC_V_CLEAR = 0x00010
|
||||
const val CC_V_SET = 0x00020
|
||||
const val CC_V_UNDEF = 0x00030
|
||||
const val CC_V_RES = 0x00040
|
||||
const val CC_V_AND = 0x00050
|
||||
const val CC_V_OR = 0x00060
|
||||
const val CC_V_TST = 0x000f0
|
||||
|
||||
const val CC_C_CLEAR = 0x00001
|
||||
const val CC_C_SET = 0x00002
|
||||
const val CC_C_UNDEF = 0x00003
|
||||
const val CC_C_RES = 0x00004
|
||||
const val CC_C_AND = 0x00005
|
||||
const val CC_C_OR = 0x00006
|
||||
const val CC_C_TST = 0x0000f
|
||||
|
||||
private const val CC_NOT_AFFECTED_STR = "Not affected"
|
||||
private const val CC_ALWAYS_CLEAR_STR = "Always cleared"
|
||||
private const val CC_ALWAYS_SET_STR = "Always set"
|
||||
private const val CC_UNDEFINED_STR = "Undefined"
|
||||
private const val CC_RES_STR = "From result"
|
||||
private const val CC_AND_STR = "And'ed: Only cleared for zero bit"
|
||||
private const val CC_OR_STR = "Or'ed: Only set for one bit"
|
||||
|
||||
fun getCcInfo(cc: Int): Map<String, Pair<String, String>> {
|
||||
val xnzvcMap = LinkedHashMap<String, Pair<String, String>>(5)
|
||||
xnzvcMap["X"] = when (cc and CC_X_TST) {
|
||||
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||
CC_X_SET -> "1" to CC_ALWAYS_SET_STR
|
||||
CC_X_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||
CC_X_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||
CC_X_AND -> "*" to CC_AND_STR
|
||||
CC_X_OR -> "*" to CC_OR_STR
|
||||
CC_X_CARRY -> "*" to "Set the same as the carry bit"
|
||||
else -> "*" to "$CC_RES_STR (usually the bit shifted out)"
|
||||
}
|
||||
xnzvcMap["N"] = when (cc and CC_N_TST) {
|
||||
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||
CC_N_SET -> "1" to CC_ALWAYS_SET_STR
|
||||
CC_N_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||
CC_N_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||
CC_N_AND -> "*" to CC_AND_STR
|
||||
CC_N_OR -> "*" to CC_OR_STR
|
||||
else -> "*" to "$CC_RES_STR (usually if negative)"
|
||||
}
|
||||
xnzvcMap["Z"] = when (cc and CC_Z_TST) {
|
||||
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||
CC_Z_SET -> "1" to CC_ALWAYS_SET_STR
|
||||
CC_Z_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||
CC_Z_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||
CC_Z_AND -> "*" to CC_AND_STR
|
||||
CC_Z_OR -> "*" to CC_OR_STR
|
||||
else -> "*" to "$CC_RES_STR (usually if zero)"
|
||||
}
|
||||
xnzvcMap["V"] = when (cc and CC_V_TST) {
|
||||
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||
CC_V_SET -> "1" to CC_ALWAYS_SET_STR
|
||||
CC_V_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||
CC_V_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||
CC_V_AND -> "*" to CC_AND_STR
|
||||
CC_V_OR -> "*" to CC_OR_STR
|
||||
else -> "*" to "$CC_RES_STR (usually for overflows)"
|
||||
}
|
||||
xnzvcMap["C"] = when (cc and CC_V_TST) {
|
||||
0 -> "-" to CC_NOT_AFFECTED_STR
|
||||
CC_V_SET -> "1" to CC_ALWAYS_SET_STR
|
||||
CC_V_CLEAR -> "0" to CC_ALWAYS_CLEAR_STR
|
||||
CC_V_UNDEF -> "U" to CC_UNDEFINED_STR
|
||||
CC_V_AND -> "*" to CC_AND_STR
|
||||
CC_V_OR -> "*" to CC_OR_STR
|
||||
else -> "*" to "$CC_RES_STR (usually carry/borrow)"
|
||||
}
|
||||
|
||||
return xnzvcMap
|
||||
}
|
||||
|
||||
fun cc(xnzvc: String): Int {
|
||||
var result = 0
|
||||
result += when (xnzvc[0]) {
|
||||
'-' -> 0
|
||||
'0' -> CC_X_CLEAR
|
||||
'1' -> CC_X_SET
|
||||
'U' -> CC_X_UNDEF
|
||||
'*' -> CC_X_RES
|
||||
'A' -> CC_X_AND
|
||||
'O' -> CC_X_OR
|
||||
'C' -> CC_X_CARRY
|
||||
'?' -> CC_X_TST
|
||||
else -> throw IllegalArgumentException("Syntax Error")
|
||||
}
|
||||
result += when (xnzvc[1]) {
|
||||
'-' -> 0
|
||||
'0' -> CC_N_CLEAR
|
||||
'1' -> CC_N_SET
|
||||
'U' -> CC_N_UNDEF
|
||||
'*' -> CC_N_RES
|
||||
'A' -> CC_N_AND
|
||||
'O' -> CC_N_OR
|
||||
'?' -> CC_N_TST
|
||||
else -> throw IllegalArgumentException("Syntax Error")
|
||||
}
|
||||
result += when (xnzvc[2]) {
|
||||
'-' -> 0
|
||||
'0' -> CC_Z_CLEAR
|
||||
'1' -> CC_Z_SET
|
||||
'U' -> CC_Z_UNDEF
|
||||
'*' -> CC_Z_RES
|
||||
'A' -> CC_Z_AND
|
||||
'O' -> CC_Z_OR
|
||||
'?' -> CC_Z_TST
|
||||
else -> throw IllegalArgumentException("Syntax Error")
|
||||
}
|
||||
result += when (xnzvc[3]) {
|
||||
'-' -> 0
|
||||
'0' -> CC_V_CLEAR
|
||||
'1' -> CC_V_SET
|
||||
'U' -> CC_V_UNDEF
|
||||
'*' -> CC_V_RES
|
||||
'A' -> CC_V_AND
|
||||
'O' -> CC_V_OR
|
||||
'?' -> CC_V_TST
|
||||
else -> throw IllegalArgumentException("Syntax Error")
|
||||
}
|
||||
result += when (xnzvc[4]) {
|
||||
'-' -> 0
|
||||
'0' -> CC_C_CLEAR
|
||||
'1' -> CC_C_SET
|
||||
'U' -> CC_C_UNDEF
|
||||
'*' -> CC_C_RES
|
||||
'A' -> CC_C_AND
|
||||
'O' -> CC_C_OR
|
||||
'?' -> CC_C_TST
|
||||
else -> throw IllegalArgumentException("Syntax Error")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
enum class ConditionCode(val cc: String, val testedCc: Int) {
|
||||
TRUE("t", cc("-----")),
|
||||
FALSE("f", cc("-----")),
|
||||
HI("hi", cc("--?-?")),
|
||||
LS("ls", cc("--?-?")),
|
||||
CC("cc", cc("----?")),
|
||||
HS("hs", cc("----?")), // same as CC
|
||||
CS("cs", cc("----?")),
|
||||
LO("lo", cc("----?")), // same as CS
|
||||
NE("ne", cc("--?--")),
|
||||
EQ("eq", cc("--?--")),
|
||||
VC("vc", cc("---?-")),
|
||||
VS("vs", cc("---?-")),
|
||||
PL("pl", cc("-?---")),
|
||||
MI("mi", cc("-?---")),
|
||||
GE("ge", cc("-?-?-")),
|
||||
LT("lt", cc("-?-?-")),
|
||||
GT("gt", cc("-???-")),
|
||||
LE("le", cc("-???-"));
|
||||
|
||||
companion object {
|
||||
private val NAME_TO_CC_MAP = values().associateBy { it.cc }
|
||||
|
||||
fun getCcFromName(cc: String) = NAME_TO_CC_MAP[cc.lowercase()]!!
|
||||
|
||||
fun getCcFromMnemonic(originalMnemonic: String, mnemonic: String) =
|
||||
// handle special case for dbra
|
||||
if (mnemonic.equals("dbra", ignoreCase = true)) {
|
||||
FALSE
|
||||
} else {
|
||||
NAME_TO_CC_MAP[mnemonic.removePrefix(originalMnemonic.removeSuffix("CC")).lowercase()]!!
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+146
@@ -0,0 +1,146 @@
|
||||
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.asm.getCcInfo
|
||||
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 hasSameCcsForEverything = isaData.modes.map { it.affectedCc }.distinct().count() == 1
|
||||
var alreadyShownCcsOnce = false
|
||||
val mnemonicInfoRows = HtmlBuilder()
|
||||
mnemonicInfoRows.appendWithSeparators(HtmlChunk.tag("tr").child(HtmlChunk.hr().wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL).attr("colspan", "3")),
|
||||
isaData.modes.map { allowedAdrMode ->
|
||||
val addressModeInfoRows = HtmlBuilder()
|
||||
val headerCells = if (allowedAdrMode.op2 != null) {
|
||||
listOf(
|
||||
HtmlChunk.text("Mnemonic / CCs").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||
HtmlChunk.text("Operand 1").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||
HtmlChunk.text("Operand 2").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
|
||||
)
|
||||
} else if (allowedAdrMode.op1 != null) {
|
||||
listOf(
|
||||
HtmlChunk.text("Mnemonic / CCs").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL),
|
||||
HtmlChunk.text("Operand").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL)
|
||||
)
|
||||
} else {
|
||||
listOf(HtmlChunk.text("Mnemonic / CCs").wrapWith(DocumentationMarkup.SECTION_HEADER_CELL))
|
||||
}
|
||||
addressModeInfoRows.append(HtmlChunk.tag("tr").children(headerCells))
|
||||
|
||||
val contentBuilder = HtmlBuilder()
|
||||
val mnemonics = findOpSizeDescriptions(allowedAdrMode.size)
|
||||
.map { HtmlChunk.text(isaData.mnemonic + it) }
|
||||
contentBuilder.appendWithSeparators(HtmlChunk.br(), mnemonics)
|
||||
contentBuilder.append(HtmlChunk.hr())
|
||||
if (alreadyShownCcsOnce && hasSameCcsForEverything) {
|
||||
contentBuilder.append(HtmlChunk.text("Condition Codes: Same as above"))
|
||||
} else {
|
||||
alreadyShownCcsOnce = true
|
||||
contentBuilder.append(HtmlChunk.text("Condition Codes: "))
|
||||
contentBuilder.append(HtmlChunk.br())
|
||||
if (allowedAdrMode.affectedCc == 0) {
|
||||
contentBuilder.append(HtmlChunk.text("Not affected."))
|
||||
} else {
|
||||
val ccMap = getCcInfo(allowedAdrMode.affectedCc)
|
||||
val ccShortTableRows = HtmlBuilder()
|
||||
ccShortTableRows.append(
|
||||
HtmlChunk.tag("tr").children(ccMap.keys.map { HtmlChunk.text(it).wrapWith(DocumentationMarkup.SECTION_HEADER_CELL) })
|
||||
)
|
||||
ccShortTableRows.append(
|
||||
HtmlChunk.tag("tr").children(ccMap.values.map {
|
||||
HtmlChunk.text(it.first).wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL)
|
||||
})
|
||||
)
|
||||
contentBuilder.append(ccShortTableRows.wrapWith(DocumentationMarkup.SECTIONS_TABLE))
|
||||
contentBuilder.appendWithSeparators(HtmlChunk.br(), ccMap.map {
|
||||
HtmlChunk.text(it.key + " - " + it.value.second)
|
||||
})
|
||||
}
|
||||
}
|
||||
val cellsPerRow = ArrayList<HtmlChunk>(3)
|
||||
cellsPerRow.add(contentBuilder.toFragment())
|
||||
|
||||
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op1))
|
||||
if (allowedAdrMode.op1 != null) cellsPerRow.add(collectAddressModes(allowedAdrMode.op2))
|
||||
|
||||
addressModeInfoRows.append(HtmlChunk.tag("tr").children(cellsPerRow.map { it.wrapWith(DocumentationMarkup.SECTION_CONTENT_CELL) }))
|
||||
addressModeInfoRows.toFragment()
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
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.utils.M68kIsaUtil.checkIfInstructionUsesRegister
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.evaluateRegisterUse
|
||||
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 = ArrayList<HtmlChunk>()
|
||||
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_SIZE_MASK and totalRwm.inv()
|
||||
}
|
||||
} else {
|
||||
RWM_SIZE_MASK and (((cursorRwm and RWM_MODIFY_L) ushr RWM_MODIFY_SHIFT) or ((cursorRwm and RWM_READ_L) ushr RWM_READ_SHIFT))
|
||||
}
|
||||
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 RWM_MODIFY_SHIFT) or (cursorRwm ushr RWM_READ_SHIFT)) 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?
|
||||
): List<HtmlChunk> {
|
||||
var missingBits = rwmBits
|
||||
var currStatement = startingStatement
|
||||
val statementLines = ArrayList<HtmlChunk>()
|
||||
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 -> "uses $rn.b"
|
||||
RWM_READ_W -> "uses $rn.w"
|
||||
RWM_READ_L -> "uses $rn.l"
|
||||
RWM_MODIFY_B -> "changes $rn.b"
|
||||
RWM_MODIFY_W -> "changes $rn.w"
|
||||
RWM_MODIFY_L -> "changes $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()))
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package de.platon42.intellij.plugins.m68k.inspections
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.SmartList
|
||||
import de.platon42.intellij.plugins.m68k.asm.*
|
||||
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingInstructions
|
||||
import de.platon42.intellij.plugins.m68k.psi.*
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.checkIfInstructionUsesRegister
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.evaluateRegisterUse
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.getConcreteTestedCcFromMnemonic
|
||||
|
||||
class M68kDeadWriteInspection : AbstractBaseM68kLocalInspectionTool() {
|
||||
|
||||
companion object {
|
||||
private const val DISPLAY_NAME = "Dead writes to registers"
|
||||
|
||||
private const val DEAD_WRITE_MSG_TEMPLATE = "Register %s is overwritten later without being used"
|
||||
private const val POSSIBLY_DEAD_WRITE_MSG_TEMPLATE = "Register %s is overwritten later (only CC evaluated?)"
|
||||
}
|
||||
|
||||
override fun getDisplayName() = DISPLAY_NAME
|
||||
|
||||
override fun checkAsmInstruction(asmInstruction: M68kAsmInstruction, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? {
|
||||
val asmOp = asmInstruction.asmOp
|
||||
if (asmInstruction.addressingModeList.isEmpty()) return emptyArray()
|
||||
|
||||
val isaDataCandidates = findMatchingInstructions(asmOp.mnemonic)
|
||||
if (isaDataCandidates.isEmpty()) return emptyArray()
|
||||
val (_, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return emptyArray()
|
||||
|
||||
val opSize = M68kIsaUtil.getOpSizeOrDefault(asmInstruction.asmOp.opSize, adrMode)
|
||||
val rwm1 = M68kIsaUtil.modifyRwmWithOpsize((adrMode.modInfo ushr RWM_OP1_SHIFT) and RWM_OP_MASK, opSize)
|
||||
val rwm2 = if (asmInstruction.addressingModeList.size > 1) M68kIsaUtil.modifyRwmWithOpsize(
|
||||
(adrMode.modInfo ushr RWM_OP2_SHIFT) and RWM_OP_MASK, opSize
|
||||
) else 0
|
||||
val regsWritten = M68kAddressModeUtil.getReadWriteModifyRegisters(asmInstruction.addressingModeList[0], rwm1).asSequence()
|
||||
.plus(M68kAddressModeUtil.getReadWriteModifyRegisters(asmInstruction.addressingModeList.getOrNull(1), rwm2))
|
||||
.plus(M68kAddressModeUtil.getOtherReadWriteModifyRegisters(adrMode.modInfo))
|
||||
.filter { (it.second and RWM_SET_L) > 0 }
|
||||
.distinct()
|
||||
.toList()
|
||||
|
||||
val hints = SmartList<ProblemDescriptor>()
|
||||
for (regPair in regsWritten) {
|
||||
val register = regPair.first
|
||||
var rwm = regPair.second
|
||||
var currStatement = asmInstruction.parent as M68kStatement
|
||||
|
||||
var ccModification = adrMode.affectedCc
|
||||
var ccOverwritten = false
|
||||
var ccTested = false
|
||||
var hasModification = false
|
||||
|
||||
while (true) {
|
||||
currStatement = PsiTreeUtil.getNextSiblingOfType(currStatement, M68kStatement::class.java) ?: break
|
||||
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
||||
if (globalLabel != null) break
|
||||
if (PsiTreeUtil.getChildOfType(currStatement, M68kPreprocessorDirective::class.java) != null) break
|
||||
|
||||
// as we cannot evaluate macros right now, abort at macros containing the register name (only lower case for simplicity)
|
||||
val macroCall = PsiTreeUtil.getChildOfType(currStatement, M68kMacroCall::class.java)
|
||||
if (macroCall?.exprList?.any { it.textMatches(register.regname) } == true) break
|
||||
|
||||
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
|
||||
val (isaData, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: continue
|
||||
if (isaData.changesControlFlow) break
|
||||
val testedCc = getConcreteTestedCcFromMnemonic(currAsmInstruction.asmOp.mnemonic, isaData, currAdrMode)
|
||||
if (((testedCc and ccModification) > 0) && !ccOverwritten) ccTested = true
|
||||
if (currAdrMode.affectedCc != 0) ccOverwritten = true
|
||||
if (checkIfInstructionUsesRegister(currAsmInstruction, register)) {
|
||||
val totalRwms = evaluateRegisterUse(currAsmInstruction, currAdrMode, register).reduce(Int::or)
|
||||
if (totalRwms and RWM_READ_L > 0) break
|
||||
if (totalRwms and RWM_MODIFY_L > 0) {
|
||||
hasModification = true
|
||||
ccOverwritten = false
|
||||
ccModification = ccModification or currAdrMode.affectedCc
|
||||
rwm = (totalRwms ushr RWM_MODIFY_SHIFT) and RWM_SET_L
|
||||
}
|
||||
if (totalRwms and RWM_SET_L >= rwm) {
|
||||
if (ccTested && hasModification) {
|
||||
break
|
||||
}
|
||||
hints.add(
|
||||
manager.createProblemDescriptor(
|
||||
asmInstruction,
|
||||
asmInstruction,
|
||||
(if (ccTested) POSSIBLY_DEAD_WRITE_MSG_TEMPLATE else DEAD_WRITE_MSG_TEMPLATE).format(register.regname),
|
||||
if (ccTested) ProblemHighlightType.WEAK_WARNING else ProblemHighlightType.WARNING,
|
||||
isOnTheFly
|
||||
)
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hints.toTypedArray()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package de.platon42.intellij.plugins.m68k.inspections
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingInstructions
|
||||
import de.platon42.intellij.plugins.m68k.psi.*
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil
|
||||
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction
|
||||
|
||||
class M68kUnexpectedConditionalInstructionInspection : AbstractBaseM68kLocalInspectionTool() {
|
||||
|
||||
companion object {
|
||||
private const val DISPLAY_NAME = "Unaffected condition codes before conditional instruction"
|
||||
|
||||
private const val UNAFFECTED_CONDITION_CODES_MSG_TEMPLATE = "Condition codes unaffected by instruction (%s - %s)"
|
||||
}
|
||||
|
||||
override fun getDisplayName() = DISPLAY_NAME
|
||||
|
||||
override fun checkAsmInstruction(asmInstruction: M68kAsmInstruction, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? {
|
||||
val asmOp = asmInstruction.asmOp
|
||||
if (asmInstruction.addressingModeList.isEmpty()) return emptyArray()
|
||||
|
||||
val isaDataCandidates = findMatchingInstructions(asmOp.mnemonic)
|
||||
if (isaDataCandidates.isEmpty()) return emptyArray()
|
||||
val (isaData, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return emptyArray()
|
||||
if ((adrMode.affectedCc > 0) || (adrMode.testedCc > 0) || isaData.changesControlFlow) return emptyArray()
|
||||
|
||||
var currStatement = asmInstruction.parent as M68kStatement
|
||||
while (true) {
|
||||
currStatement = PsiTreeUtil.getNextSiblingOfType(currStatement, M68kStatement::class.java) ?: break
|
||||
val globalLabel = PsiTreeUtil.findChildOfType(currStatement, M68kGlobalLabel::class.java)
|
||||
if (globalLabel != null) break
|
||||
if (PsiTreeUtil.findChildOfAnyType(currStatement, M68kMacroCall::class.java, M68kPreprocessorDirective::class.java) != null) break
|
||||
val currAsmInstruction = PsiTreeUtil.getChildOfType(currStatement, M68kAsmInstruction::class.java) ?: continue
|
||||
val (currIsaData, currAdrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(currAsmInstruction) ?: break
|
||||
val testedCc = M68kIsaUtil.getConcreteTestedCcFromMnemonic(currAsmInstruction.asmOp.mnemonic, currIsaData, currAdrMode)
|
||||
if (testedCc == 0) break
|
||||
|
||||
return arrayOf(
|
||||
manager.createProblemDescriptor(
|
||||
asmInstruction,
|
||||
asmInstruction,
|
||||
UNAFFECTED_CONDITION_CODES_MSG_TEMPLATE.format(isaData.mnemonic, isaData.description),
|
||||
ProblemHighlightType.WARNING,
|
||||
isOnTheFly
|
||||
)
|
||||
)
|
||||
}
|
||||
return emptyArray()
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import de.platon42.intellij.plugins.m68k.psi.M68kTypes
|
||||
object LexerUtil {
|
||||
|
||||
private val ASSIGNMENT_SEPARATORS = charArrayOf(' ', '\t', '=', ':')
|
||||
private val TOKEN_SEPARATORS = charArrayOf(' ', '\t')
|
||||
private val TOKEN_SEPARATORS = charArrayOf(' ', '\t', ':')
|
||||
|
||||
@JvmStatic
|
||||
fun isAsmMnemonic(text: CharSequence) = mnemonics.contains(text.toString().lowercase())
|
||||
|
||||
@@ -2,7 +2,7 @@ package de.platon42.intellij.plugins.m68k.lexer
|
||||
|
||||
data class M68kLexerPrefs(
|
||||
var spaceIntroducesComment: Boolean = false,
|
||||
var maxLinesPerMacro: Int = 50,
|
||||
var maxLinesPerMacro: Int = 250,
|
||||
var macroSectionUnparsed: Boolean = false,
|
||||
var macroParametersUnparsed: Boolean = true
|
||||
)
|
||||
@@ -51,7 +51,7 @@ LOCAL_LABEL=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:?)|(([:letter:]|_)([:lett
|
||||
LOCAL_LABEL_WC=(\.([:letter:]|_)([:letter:]|[:digit:]|_)*:)|(([:letter:]|_)([:letter:]|[:digit:]|_)*\$:)
|
||||
GLOBAL_LABEL=(([:letter:]|_)([:letter:]|[:digit:]|_)*:?:?)
|
||||
GLOBAL_LABEL_WC=(([:letter:]|_)([:letter:]|[:digit:]|_)*::?)
|
||||
MACRO_DEF_LEFT=(([:letter:]|_)(([:letter:]|[:digit:]|_))*)\p{Blank}+macro\p{Blank}*
|
||||
MACRO_DEF_LEFT=(([:letter:]|_)(([:letter:]|[:digit:]|_))*)(\p{Blank}+|:\p{Blank}*)macro\p{Blank}*
|
||||
MACRO_END_TAG=\p{Blank}+endm\p{Blank}*[^;\r\n]*
|
||||
//MNEMONIC=(([:letter:])+)
|
||||
SYMBOL=(([:letter:]|_|\.)(([:letter:]|[:digit:]|[_\$]))*)
|
||||
@@ -62,7 +62,7 @@ OPSIZE_BS=(\.[bs])
|
||||
OPSIZE_W=(\.w)
|
||||
OPSIZE_L=(\.l)
|
||||
BINARY=(%[01]+)
|
||||
HEXADECIMAL=(\$[0-9a-f]+)
|
||||
HEXADECIMAL=(\$[0-9a-fA-F]+)
|
||||
OCTAL=(@[0-7]+)
|
||||
DECIMAL=([0-9]+)
|
||||
STRINGLIT=(`([^`\\\r\n]|\\.)*`|'([^'\\\r\n]|\\.)*'|\"([^\"\\\r\n]|\\.)*\")
|
||||
@@ -123,7 +123,7 @@ PLAIN_MACRO_LINE=[^;\r\n]+
|
||||
{MACRONAME} { return handleMacroMode(this); }
|
||||
}
|
||||
|
||||
<INSTRPART> {
|
||||
<INSTRPART,MACRODEF> {
|
||||
":" { return COLON; }
|
||||
// {MNEMONIC} { if(isAsmMnemonic(yytext())) { yybegin(ASMINSTR); return MNEMONIC; } else { return SYMBOL; } }
|
||||
}
|
||||
|
||||
@@ -161,11 +161,17 @@ GlobalLabel ::= GLOBAL_LABEL_DEF COLON* {
|
||||
|
||||
private Label ::= LocalLabel | GlobalLabel
|
||||
|
||||
OperandSize ::= (OPSIZE_BS|OPSIZE_W|OPSIZE_L) { name = ".s|.b|.w|.l" }
|
||||
OperandSize ::= (OPSIZE_BS|OPSIZE_W|OPSIZE_L) {
|
||||
name = ".s|.b|.w|.l"
|
||||
methods = [getSize]
|
||||
}
|
||||
AddressSize ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
|
||||
DataWidth ::= (OPSIZE_W|OPSIZE_L) { name = ".w|.l" }
|
||||
|
||||
AsmOp ::= MNEMONIC OperandSize?
|
||||
AsmOp ::= MNEMONIC OperandSize? {
|
||||
name = "mnemonic"
|
||||
methods = [getMnemonic getOpSize]
|
||||
}
|
||||
|
||||
PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
||||
PreprocessorOperands?
|
||||
@@ -173,8 +179,8 @@ PreprocessorDirective ::= Label? (DATA_DIRECTIVE | OTHER_DIRECTIVE)
|
||||
MacroPlainLine ::= MACRO_LINE
|
||||
MacroNameDefinition ::= MACRO_NAME
|
||||
|
||||
MacroDefinition ::= ((MacroNameDefinition MACRO_TAG)|(MACRO_TAG MacroNameDefinition)) MacroPlainLine* MACRO_END_TAG {
|
||||
pin=1
|
||||
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"
|
||||
@@ -228,6 +234,14 @@ Register ::= DataRegister | AddressRegister | SpecialRegister
|
||||
|
||||
private DataOrAddressRegister ::= DataRegister | AddressRegister { name = "data or address register"}
|
||||
|
||||
IndexRegister ::= DataOrAddressRegister DataWidth?
|
||||
{
|
||||
name = "index register"
|
||||
methods = [
|
||||
isLongWidth
|
||||
]
|
||||
}
|
||||
|
||||
AddressingMode ::= ImmediateData
|
||||
| AddressRegisterIndirectPreDecAddressingMode
|
||||
| AddressRegisterIndirectPostIncAddressingMode
|
||||
@@ -249,20 +263,108 @@ AddressingMode ::= ImmediateData
|
||||
SpecialRegisterDirectAddressingMode ::= SpecialRegister
|
||||
DataRegisterDirectAddressingMode ::= DataRegister !(OP_MINUS|OP_AR_DIV)
|
||||
AddressRegisterDirectAddressingMode ::= AddressRegister !(OP_MINUS|OP_AR_DIV)
|
||||
AddressRegisterIndirectAddressingMode ::= ROUND_L AddressRegister ROUND_R !OP_PLUS
|
||||
AddressRegisterIndirectPostIncAddressingMode ::= ROUND_L AddressRegister ROUND_R OP_PLUS
|
||||
AddressRegisterIndirectPreDecAddressingMode ::= OP_MINUS ROUND_L AddressRegister ROUND_R
|
||||
AddressRegisterIndirectAddressingMode ::= ROUND_L AddressRegister ROUND_R !OP_PLUS { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
|
||||
AddressRegisterIndirectPostIncAddressingMode ::= ROUND_L AddressRegister ROUND_R OP_PLUS { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
|
||||
AddressRegisterIndirectPreDecAddressingMode ::= OP_MINUS ROUND_L AddressRegister ROUND_R { implements = "de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect" }
|
||||
AddressRegisterIndirectWithDisplacementOldAddressingMode ::= expr ROUND_L AddressRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
AddressRegisterIndirectWithDisplacementNewAddressingMode ::= ROUND_L expr SEPARATOR AddressRegister ROUND_R
|
||||
AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
AddressRegisterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
AddressRegisterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? AddressRegister SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithAddressRegisterIndirect"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
ProgramCounterIndirectWithDisplacementOldAddressingMode ::= (ROUND_L PC ROUND_R) | (expr ROUND_L PC ROUND_R)
|
||||
{
|
||||
implements = ["de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
ProgramCounterIndirectWithDisplacementNewAddressingMode ::= ROUND_L expr SEPARATOR PC ROUND_R
|
||||
ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? PC SEPARATOR DataOrAddressRegister DataWidth? ROUND_R
|
||||
{
|
||||
implements = ["de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
ProgramCounterIndirectWithIndexOldAddressingMode ::= expr? ROUND_L PC SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
ProgramCounterIndirectWithIndexNewAddressingMode ::= ROUND_L (expr SEPARATOR)? PC SEPARATOR IndexRegister ROUND_R
|
||||
{
|
||||
implements = [
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithDisplacement"
|
||||
"de.platon42.intellij.plugins.m68k.psi.M68kWithIndexRegister"
|
||||
]
|
||||
methods = [
|
||||
displacement = "expr"
|
||||
]
|
||||
}
|
||||
|
||||
AbsoluteAddressAddressingMode ::= expr AddressSize? !ROUND_L
|
||||
private RegisterRange ::= (DataOrAddressRegister OP_MINUS DataOrAddressRegister)
|
||||
RegisterListAddressingMode ::= (DataOrAddressRegister|RegisterRange) ((OP_AR_DIV|OP_MINUS) (DataOrAddressRegister|RegisterRange))*
|
||||
|
||||
RegisterRange ::= (DataRegister OP_MINUS DataRegister) | (AddressRegister OP_MINUS AddressRegister) | (DataRegister OP_MINUS AddressRegister) {
|
||||
name = "register range"
|
||||
methods = [
|
||||
startRegister = "Register[0]"
|
||||
endRegister = "Register[1]"
|
||||
]
|
||||
}
|
||||
|
||||
RegisterListAddressingMode ::= (RegisterRange|DataOrAddressRegister) (OP_AR_DIV (RegisterRange|DataOrAddressRegister))*
|
||||
{
|
||||
name = "register list"
|
||||
methods = [ getRegisters ]
|
||||
}
|
||||
|
||||
ImmediateData ::= HASH expr {
|
||||
name = "immediate data"
|
||||
extends = AddressingMode
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import de.platon42.intellij.plugins.m68k.asm.*
|
||||
|
||||
object M68kAddressModeUtil {
|
||||
fun getAddressModeForType(addressingMode: M68kAddressingMode?): AddressMode? {
|
||||
if (addressingMode == null) return null
|
||||
return when (addressingMode) {
|
||||
is M68kImmediateData -> AddressMode.IMMEDIATE_DATA
|
||||
is M68kAddressRegisterIndirectAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT
|
||||
is M68kAddressRegisterIndirectPostIncAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC
|
||||
is M68kAddressRegisterIndirectPreDecAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC
|
||||
is M68kAddressRegisterIndirectWithDisplacementNewAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT
|
||||
is M68kAddressRegisterIndirectWithDisplacementOldAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT
|
||||
is M68kAddressRegisterIndirectWithIndexNewAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX
|
||||
is M68kAddressRegisterIndirectWithIndexOldAddressingMode -> AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX
|
||||
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT
|
||||
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT
|
||||
is M68kProgramCounterIndirectWithIndexNewAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
|
||||
is M68kProgramCounterIndirectWithIndexOldAddressingMode -> AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX
|
||||
is M68kSpecialRegisterDirectAddressingMode -> AddressMode.SPECIAL_REGISTER_DIRECT
|
||||
is M68kDataRegisterDirectAddressingMode -> AddressMode.DATA_REGISTER_DIRECT
|
||||
is M68kAddressRegisterDirectAddressingMode -> AddressMode.ADDRESS_REGISTER_DIRECT
|
||||
is M68kRegisterListAddressingMode -> AddressMode.REGISTER_LIST
|
||||
is M68kAbsoluteAddressAddressingMode -> AddressMode.ABSOLUTE_ADDRESS
|
||||
else -> throw IllegalArgumentException("Unknown addressing mode $addressingMode")
|
||||
}
|
||||
}
|
||||
|
||||
fun getOtherReadWriteModifyRegisters(rwm: Int): List<Pair<Register, Int>> {
|
||||
if (rwm and RWM_MODIFY_STACK > 0) {
|
||||
return listOf(Register.A7 to RWM_MODIFY_L)
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
fun getReadWriteModifyRegisters(addressingMode: M68kAddressingMode?, rwm: Int): List<Pair<Register, Int>> {
|
||||
if (addressingMode == null) return emptyList()
|
||||
return when (addressingMode) {
|
||||
is M68kImmediateData,
|
||||
is M68kSpecialRegisterDirectAddressingMode,
|
||||
is M68kProgramCounterIndirectWithDisplacementNewAddressingMode,
|
||||
is M68kProgramCounterIndirectWithDisplacementOldAddressingMode,
|
||||
is M68kAbsoluteAddressAddressingMode -> emptyList()
|
||||
|
||||
is M68kAddressRegisterIndirectPostIncAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to (RWM_READ_L or RWM_MODIFY_L))
|
||||
is M68kAddressRegisterIndirectPreDecAddressingMode -> listOf(Register.getRegFromName(addressingMode.addressRegister.text) to (RWM_READ_L or 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()
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex
|
||||
object M68kLookupUtil {
|
||||
|
||||
fun findAllGlobalLabels(project: Project): List<M68kGlobalLabel> {
|
||||
val results: MutableList<M68kGlobalLabel> = ArrayList()
|
||||
val results = ArrayList<M68kGlobalLabel>()
|
||||
StubIndex.getInstance().processAllKeys(M68kGlobalLabelStubIndex.KEY, project)
|
||||
{
|
||||
results.addAll(StubIndex.getElements(M68kGlobalLabelStubIndex.KEY, it, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java))
|
||||
@@ -21,7 +21,7 @@ object M68kLookupUtil {
|
||||
}
|
||||
|
||||
fun findAllGlobalLabels(file: M68kFile): List<M68kGlobalLabel> {
|
||||
val results: MutableList<M68kGlobalLabel> = ArrayList()
|
||||
val results = ArrayList<M68kGlobalLabel>()
|
||||
StubIndex.getInstance().processAllKeys(
|
||||
M68kGlobalLabelStubIndex.KEY,
|
||||
{
|
||||
@@ -44,7 +44,7 @@ object M68kLookupUtil {
|
||||
|
||||
fun findAllLocalLabels(globalLabel: M68kGlobalLabel): List<M68kLocalLabel> {
|
||||
val statement = PsiTreeUtil.getStubOrPsiParentOfType(globalLabel, M68kStatement::class.java)!!
|
||||
val results: MutableList<M68kLocalLabel> = ArrayList()
|
||||
val results = ArrayList<M68kLocalLabel>()
|
||||
var currentStatement = PsiTreeUtil.getNextSiblingOfType(statement, M68kStatement::class.java)
|
||||
while (currentStatement != null) {
|
||||
val child = currentStatement.firstChild
|
||||
@@ -56,7 +56,7 @@ object M68kLookupUtil {
|
||||
}
|
||||
|
||||
fun findAllSymbolDefinitions(project: Project): List<M68kSymbolDefinition> {
|
||||
val results: MutableList<M68kSymbolDefinition> = ArrayList()
|
||||
val results = ArrayList<M68kSymbolDefinition>()
|
||||
StubIndex.getInstance().processAllKeys(M68kSymbolDefinitionStubIndex.KEY, project)
|
||||
{
|
||||
results.addAll(
|
||||
@@ -74,7 +74,7 @@ object M68kLookupUtil {
|
||||
}
|
||||
|
||||
fun findAllSymbolDefinitions(file: M68kFile): List<M68kSymbolDefinition> {
|
||||
val results: MutableList<M68kSymbolDefinition> = ArrayList()
|
||||
val results = ArrayList<M68kSymbolDefinition>()
|
||||
StubIndex.getInstance().processAllKeys(
|
||||
M68kSymbolDefinitionStubIndex.KEY,
|
||||
{
|
||||
@@ -97,7 +97,7 @@ object M68kLookupUtil {
|
||||
|
||||
|
||||
fun findAllMacroDefinitions(project: Project): List<M68kMacroDefinition> {
|
||||
val results: MutableList<M68kMacroDefinition> = ArrayList()
|
||||
val results = ArrayList<M68kMacroDefinition>()
|
||||
StubIndex.getInstance().processAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
|
||||
{
|
||||
results.addAll(
|
||||
@@ -115,7 +115,7 @@ object M68kLookupUtil {
|
||||
}
|
||||
|
||||
fun findAllMacroDefinitions(file: M68kFile): List<M68kMacroDefinition> {
|
||||
val results: MutableList<M68kMacroDefinition> = ArrayList()
|
||||
val results = ArrayList<M68kMacroDefinition>()
|
||||
StubIndex.getInstance().processAllKeys(
|
||||
M68kMacroDefinitionStubIndex.KEY,
|
||||
{
|
||||
@@ -135,6 +135,4 @@ object M68kLookupUtil {
|
||||
}
|
||||
|
||||
fun findAllMacroDefinitionNames(project: Project): Collection<String> = StubIndex.getInstance().getAllKeys(M68kMacroDefinitionStubIndex.KEY, project)
|
||||
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package de.platon42.intellij.plugins.m68k.psi
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import de.platon42.intellij.plugins.m68k.asm.*
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createGlobalLabel
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createLocalLabel
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kElementFactory.createMacroDefinition
|
||||
@@ -94,4 +95,49 @@ object M68kPsiImplUtil {
|
||||
@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 = HashSet<Register>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class M68kChooseByNameContributor : ChooseByNameContributorEx {
|
||||
// }
|
||||
|
||||
// override fun getItemsByName(name: String, pattern: String, project: Project, includeNonProjectItems: Boolean): Array<NavigationItem> {
|
||||
// val result: MutableList<NavigationItem> = ArrayList()
|
||||
// val result = ArrayList<NavigationItem>()
|
||||
// processElementsWithName(name, result::add, FindSymbolParameters.wrap(pattern, project, includeNonProjectItems))
|
||||
// return result.toTypedArray()
|
||||
// }
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class M68kGlobalLabelSymbolReference(element: M68kSymbolReference) :
|
||||
val refName = ref.element.symbolName
|
||||
val project = ref.element.project
|
||||
|
||||
val targets: MutableList<M68kNamedElement> = SmartList()
|
||||
val targets = SmartList<M68kNamedElement>()
|
||||
StubIndex.getInstance()
|
||||
.processElements(M68kGlobalLabelStubIndex.KEY, refName, project, GlobalSearchScope.allScope(project), M68kGlobalLabel::class.java)
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ class M68kLocalLabelReference(element: M68kSymbolReference) : PsiPolyVariantRefe
|
||||
|
||||
fun findLocalLabels(element: M68kSymbolReference, predicate: (M68kLocalLabel) -> Boolean): List<M68kLocalLabel> {
|
||||
val statement = PsiTreeUtil.getStubOrPsiParentOfType(element, M68kStatement::class.java)!!
|
||||
val results: MutableList<M68kLocalLabel> = SmartList()
|
||||
val results = SmartList<M68kLocalLabel>()
|
||||
// go backward
|
||||
var currentStatement = PsiTreeUtil.getPrevSiblingOfType(statement, M68kStatement::class.java)
|
||||
while (currentStatement != null) {
|
||||
|
||||
@@ -25,7 +25,7 @@ class M68kMacroReference(element: M68kMacroCall) :
|
||||
val macroName = ref.element.macroName
|
||||
val project = ref.element.project
|
||||
|
||||
val targets: MutableList<M68kMacroDefinition> = SmartList()
|
||||
val targets = SmartList<M68kMacroDefinition>()
|
||||
StubIndex.getInstance()
|
||||
.processElements(M68kMacroDefinitionStubIndex.KEY, macroName, project, GlobalSearchScope.allScope(project), M68kMacroDefinition::class.java)
|
||||
{
|
||||
|
||||
+59
-6
@@ -3,24 +3,77 @@ package de.platon42.intellij.plugins.m68k.structureview
|
||||
import com.intellij.ide.structureView.StructureViewModel.ElementInfoProvider
|
||||
import com.intellij.ide.structureView.StructureViewModelBase
|
||||
import com.intellij.ide.structureView.StructureViewTreeElement
|
||||
import com.intellij.ide.util.treeView.smartTree.Sorter
|
||||
import com.intellij.ide.util.treeView.smartTree.*
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiFile
|
||||
import de.platon42.intellij.plugins.m68k.M68kIcons
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kGlobalLabel
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kLocalLabel
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kMacroDefinition
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kSymbolDefinition
|
||||
|
||||
class M68kStructureViewModel(psiFile: PsiFile, editor: Editor?) :
|
||||
StructureViewModelBase(psiFile, editor, M68kStructureViewElement(psiFile)), ElementInfoProvider {
|
||||
|
||||
override fun isAlwaysShowsPlus(element: StructureViewTreeElement): Boolean {
|
||||
return false
|
||||
companion object {
|
||||
val FILTERS = arrayOf(SymbolsFilter(), MacrosFilter(), GlobalLabelFilter(), LocalLabelFilter())
|
||||
|
||||
const val SYMBOLS_FILTER_ID = "SHOW_SYMBOLS"
|
||||
const val MACROS_FILTER_ID = "SHOW_MACROS"
|
||||
const val GLOBAL_LABEL_FILTER_ID = "SHOW_GLOBAL_LABELS"
|
||||
const val LOCAL_LABEL_FILTER_ID = "SHOW_LOCAL_LABELS"
|
||||
}
|
||||
|
||||
override fun isAlwaysShowsPlus(element: StructureViewTreeElement): Boolean = false
|
||||
|
||||
override fun isAlwaysLeaf(element: StructureViewTreeElement): Boolean {
|
||||
return element.value is M68kLocalLabel || element.value is M68kMacroDefinition
|
||||
return when (element.value) {
|
||||
is M68kLocalLabel, is M68kMacroDefinition, is M68kSymbolDefinition -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSorters(): Array<Sorter> {
|
||||
return arrayOf(Sorter.ALPHA_SORTER)
|
||||
override fun getSorters(): Array<Sorter> = arrayOf(Sorter.ALPHA_SORTER)
|
||||
|
||||
override fun getFilters(): Array<Filter> = FILTERS
|
||||
|
||||
class SymbolsFilter : Filter {
|
||||
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Symbols", null, M68kIcons.SYMBOL_DEF)
|
||||
|
||||
override fun getName(): String = SYMBOLS_FILTER_ID
|
||||
|
||||
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kSymbolDefinition
|
||||
|
||||
override fun isReverted() = true
|
||||
}
|
||||
|
||||
class MacrosFilter : Filter {
|
||||
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Macros", null, M68kIcons.MACRO_DEF)
|
||||
|
||||
override fun getName(): String = MACROS_FILTER_ID
|
||||
|
||||
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kMacroDefinition
|
||||
|
||||
override fun isReverted() = true
|
||||
}
|
||||
|
||||
class GlobalLabelFilter : Filter {
|
||||
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Global Labels", null, M68kIcons.GLOBAL_LABEL)
|
||||
|
||||
override fun getName(): String = GLOBAL_LABEL_FILTER_ID
|
||||
|
||||
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kGlobalLabel
|
||||
|
||||
override fun isReverted() = true
|
||||
}
|
||||
|
||||
class LocalLabelFilter : Filter {
|
||||
override fun getPresentation(): ActionPresentation = ActionPresentationData("Show Local Labels", null, M68kIcons.LOCAL_LABEL)
|
||||
|
||||
override fun getName(): String = LOCAL_LABEL_FILTER_ID
|
||||
|
||||
override fun isVisible(treeNode: TreeElement?) = (treeNode as? StructureViewTreeElement)?.value !is M68kLocalLabel
|
||||
|
||||
override fun isReverted() = true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package de.platon42.intellij.plugins.m68k.utils
|
||||
|
||||
import de.platon42.intellij.plugins.m68k.asm.*
|
||||
import de.platon42.intellij.plugins.m68k.asm.ConditionCode.Companion.getCcFromMnemonic
|
||||
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 checkIfInstructionUsesRegister(instruction: M68kAsmInstruction, register: Register): Boolean {
|
||||
if (instruction.addressingModeList.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
return instruction.addressingModeList.any { aml -> M68kAddressModeUtil.getReadWriteModifyRegisters(aml, 0).any { it.first == register } }
|
||||
}
|
||||
|
||||
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 M68kAddressModeUtil.getReadWriteModifyRegisters(asmInstruction.addressingModeList[0], rwm1).asSequence()
|
||||
.plus(M68kAddressModeUtil.getReadWriteModifyRegisters(asmInstruction.addressingModeList.getOrNull(1), rwm2))
|
||||
.plus(M68kAddressModeUtil.getOtherReadWriteModifyRegisters(adrMode.modInfo))
|
||||
.filter { it.first == register }
|
||||
.map { it.second }
|
||||
.distinct()
|
||||
.toList()
|
||||
}
|
||||
|
||||
fun getConcreteTestedCcFromMnemonic(mnemonic: String, isaData: IsaData, adrMode: AllowedAdrMode) =
|
||||
if (isaData.conditionCodes.isNotEmpty()) getCcFromMnemonic(isaData.mnemonic, mnemonic).testedCc else adrMode.testedCc
|
||||
|
||||
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>
|
||||
<a href="https://github.com/chrisly42/mc68000-asm-plugin/blob/main/README.md">Full documentation here...</a>
|
||||
]]></description>
|
||||
<idea-version since-build="193.5233.103"/>
|
||||
<idea-version since-build="203.5981.166"/>
|
||||
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
|
||||
@@ -33,6 +33,12 @@
|
||||
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kSymbolReferenceElementManipulator"/>
|
||||
<lang.elementManipulator forClass="de.platon42.intellij.plugins.m68k.psi.M68kMacroCall"
|
||||
implementationClass="de.platon42.intellij.plugins.m68k.refs.M68kMacroCallElementManipulator"/>
|
||||
<lang.documentationProvider language="MC68000"
|
||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kSymbolDefinitionDocumentationProvider"/>
|
||||
<lang.documentationProvider language="MC68000"
|
||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kRegisterFlowDocumentationProvider"/>
|
||||
<lang.documentationProvider language="MC68000"
|
||||
implementationClass="de.platon42.intellij.plugins.m68k.documentation.M68kInstructionDocumentationProvider"/>
|
||||
<stubElementTypeHolder class="de.platon42.intellij.plugins.m68k.stubs.M68kElementTypes"/>
|
||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/>
|
||||
<stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex"/>
|
||||
@@ -40,6 +46,16 @@
|
||||
<psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/>
|
||||
<gotoSymbolContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kChooseByNameContributor"/>
|
||||
<renameInputValidator implementation="de.platon42.intellij.plugins.m68k.psi.M68kRenameInputValidator"/>
|
||||
|
||||
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kSyntaxInspection"
|
||||
displayName="Assembly instruction validity" groupName="M68k"
|
||||
enabledByDefault="true" level="ERROR"/>
|
||||
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kDeadWriteInspection"
|
||||
displayName="Dead writes to registers" groupName="M68k"
|
||||
enabledByDefault="true" level="WARNING"/>
|
||||
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnexpectedConditionalInstructionInspection"
|
||||
displayName="Unaffected condition codes before conditional instruction" groupName="M68k"
|
||||
enabledByDefault="true" level="WARNING"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<body>
|
||||
Finds dead writes to registers, i.e. writes that will not have any effect.
|
||||
|
||||
Issues a weak warning if the instruction affects only condition codes that are later tested.
|
||||
|
||||
Analysis is terminated at the next global label or instruction that reads the register or changes control flow
|
||||
(or preprocessor statements, like conditional IF statements).
|
||||
<!-- tooltip end -->
|
||||
<p>Note: As there is no evaluation of macros right now, the inspection might report some false positives.
|
||||
|
||||
As an attempt to reduce these false positives, macros containing the register name will abort the analysis.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports wrong use of assembler instruction syntax.
|
||||
|
||||
The parser allows more combinations than supported by the target CPU.
|
||||
This inspection does a strict verification on the allowed addressing modes
|
||||
and operation size for each assembly mnemonic.
|
||||
<!-- tooltip end -->
|
||||
<p>Several different error messages may be the result of this verification,
|
||||
giving hints whether the first or the second addressing mode is unsupported,
|
||||
or if the operands should be swapped to make it a legal instruction.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<body>
|
||||
Usually, it is expected that an instruction checking the condition codes or using
|
||||
the condition codes is preceded by an instruction that actually affects the condition
|
||||
codes. This inspection checks that this is the case.
|
||||
|
||||
For example, the 'movea' and 'adda' instructions (which can be (and are!) often written
|
||||
as 'move' and 'add') do not affect the condition codes and a conditional branch
|
||||
will not work as expected.
|
||||
|
||||
However, this does not need to be a programming error. Advanced coders sometimes
|
||||
make use of the fact that instructions do not change condition codes and thus
|
||||
optimize the order of execution.
|
||||
|
||||
<!-- tooltip end -->
|
||||
Analysis is terminated at the next global label, macrocall or preprocessor statement.
|
||||
</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))
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
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 / CCs</td>
|
||||
<td class="section" valign="top">Operand 1</td>
|
||||
<td class="section" valign="top">Operand 2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">moveq.l
|
||||
<hr/>
|
||||
Condition Codes: <br/>
|
||||
<table class="sections">
|
||||
<tr>
|
||||
<td class="section" valign="top">X</td>
|
||||
<td class="section" valign="top">N</td>
|
||||
<td class="section" valign="top">Z</td>
|
||||
<td class="section" valign="top">V</td>
|
||||
<td class="section" valign="top">C</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">-</td>
|
||||
<td valign="top">*</td>
|
||||
<td valign="top">*</td>
|
||||
<td valign="top">0</td>
|
||||
<td valign="top">0</td>
|
||||
</tr>
|
||||
</table>
|
||||
X - Not affected<br/>N - From result (usually if negative)<br/>Z - From result (usually if zero)<br/>V - Always cleared<br/>C - Always cleared
|
||||
</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 / CCs</td>
|
||||
<td class="section" valign="top">Operand</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">bra.s<br/>bra.b<br/>bra.w
|
||||
<hr/>
|
||||
Condition Codes: <br/>Not affected.
|
||||
</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>")
|
||||
}
|
||||
}
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
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_read_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 uses 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"> ; changes 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"> ; uses 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"> ; changes 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"> ; uses 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>
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
internal fun check_documentation_for_a_written_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 d0,d<caret>1
|
||||
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 sets d1.w</div>
|
||||
<table class="sections" style="padding-left: 8pt; padding-right: 8pt">
|
||||
<tr>
|
||||
<td colspan="3" valign="top"><b>label</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"><code>move.l <font color="#ffc800">d1</font>,-(sp)</code></td>
|
||||
<td valign="top"> ; uses d1.l</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"> </td>
|
||||
<td valign="top"><code>move.w d0,<font color="#ffc800">d1</font></code></td>
|
||||
<td valign="top"> ; sets d1.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"><b><code>move.w d0,<font color="#ffc800">d1</font></code></b></td>
|
||||
<td valign="top"> ; <--</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">d1</font>,d2</code></td>
|
||||
<td valign="top"> ; uses d1.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.l (sp)+,<font color="#ffc800">d1</font></code></td>
|
||||
<td valign="top"> ; <font color="#00ff00">sets d1.l</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
+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,19 @@
|
||||
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"))
|
||||
}
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
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 M68kDeadWriteInspectionTest : AbstractInspectionTest() {
|
||||
|
||||
@Test
|
||||
internal fun find_direct_dead_write_to_register(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
add.l d0,d2
|
||||
moveq.l #123,d1
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d1 is overwritten later without being used")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun find_direct_dead_write_to_register_with_modification(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
add.l d0,d1
|
||||
moveq.l #123,d1
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d1 is overwritten later without being used")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun no_dead_write_to_register_due_to_part_modification(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
add.b d1,d0
|
||||
moveq.l #123,d1
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun use_of_condition_code_causes_weak_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
scc d0
|
||||
moveq.l #123,d1
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d1 is overwritten later (only CC evaluated?)")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun use_of_conditional_instruction_for_non_conditional_causes_full_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
st d0
|
||||
moveq.l #123,d1
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d1 is overwritten later without being used")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun use_of_condition_code_after_modification_causes_no_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
add.b d0,d1
|
||||
seq .foo
|
||||
moveq.l #123,d1
|
||||
.foo
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun use_of_control_flow_causes_no_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.l #123,d1
|
||||
add.b d0,d1
|
||||
bra.s .foo
|
||||
moveq.l #123,d1
|
||||
.foo
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun movem_can_cause_multiple_warnings(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
movem.l (a0),d0-d7
|
||||
add.l d0,d1
|
||||
moveq.l #123,d3
|
||||
clr.l #123,d6
|
||||
movem.l (a0),d5-d7
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d5 is overwritten later without being used")
|
||||
assertHighlightings(myFixture, 1, "Register d6 is overwritten later without being used")
|
||||
assertHighlightings(myFixture, 1, "Register d7 is overwritten later without being used")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun overwrite_in_same_instruction_with_read_causes_no_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.w #123,d3
|
||||
move.w (a0,d3.w),d3
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun partial_overwrite_in_causes_no_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.w #123,d3
|
||||
move.b d2,d3
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun oversized_overwrite_in_causes_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.w #123,d3
|
||||
move.l d2,d3
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d3 is overwritten later without being used")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun conditional_write_does_not_cause_a_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
IF 0
|
||||
move.w #123,d3
|
||||
ELSE
|
||||
clr.w d3
|
||||
ENDC
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun modification_extending_width_does_not_cause_a_warning_on_smaller_write_later(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
move.b (a0)+,d0
|
||||
lsl #8,d0
|
||||
move.b (a0)+,d0
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun macro_call_with_register_name_will_not_cause_a_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
moveq.l #-1,d0
|
||||
COPRMOVE d0,bltafwm
|
||||
move.l pd_CurrPlanesPtr(a4),d0
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun macro_call_with_different_register_name_will_cause_a_warning(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kDeadWriteInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"deadwrite.asm", """
|
||||
moveq.l #-1,d0
|
||||
COPRMOVE d1,bltafwm
|
||||
move.l pd_CurrPlanesPtr(a4),d0
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Register d0 is overwritten later without being used")
|
||||
}
|
||||
}
|
||||
+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'")
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
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 M68kUnexpectedConditionalInstructionInspectionTest : AbstractInspectionTest() {
|
||||
|
||||
@Test
|
||||
internal fun movea_causes_warning_when_used_for_conditional_branching(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kUnexpectedConditionalInstructionInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"unexpectedcc.asm", """
|
||||
move.l d0,a1
|
||||
bne.s .cont
|
||||
rts
|
||||
.cont
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Condition codes unaffected by instruction (movea - Move Address)")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun no_warning_on_consecutive_conditional_branches(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kUnexpectedConditionalInstructionInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"unexpectedcc.asm", """
|
||||
move.b P61_arplist(pc,d0),d0
|
||||
beq.b .arp0
|
||||
bmi.b .arp1
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun no_warning_on_macro_call_inbetween(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kUnexpectedConditionalInstructionInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"unexpectedcc.asm", """
|
||||
move.l pd_PalCurShamPalPtr(a4),a1
|
||||
PALSTEPDOWN
|
||||
bne.s .loopline
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun no_warning_flow_control_instruction(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kUnexpectedConditionalInstructionInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"unexpectedcc.asm", """
|
||||
bsr foo
|
||||
bne.s .loopline
|
||||
"""
|
||||
)
|
||||
assertThat(myFixture.doHighlighting()).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun warning_on_conditional_set_series_with_suba(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.enableInspections(M68kUnexpectedConditionalInstructionInspection::class.java)
|
||||
myFixture.configureByText(
|
||||
"unexpectedcc.asm", """
|
||||
sub.l a0,a0
|
||||
seq d0
|
||||
sne d1
|
||||
"""
|
||||
)
|
||||
assertHighlightings(myFixture, 1, "Condition codes unaffected by instruction (suba - Subtract Address)")
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package de.platon42.intellij.plugins.m68k.parser
|
||||
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import de.platon42.intellij.jupiter.MyTestCase
|
||||
import de.platon42.intellij.jupiter.ParsingTestExtension
|
||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||
import de.platon42.intellij.plugins.m68k.asm.Register
|
||||
import de.platon42.intellij.plugins.m68k.psi.M68kRegisterListAddressingMode
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@TestDataSubPath("addressingmodes")
|
||||
@@ -85,7 +89,24 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
||||
|
||||
@Test
|
||||
internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0-a2/a4,-(sp)\n")
|
||||
testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n")
|
||||
val element = testCase.file.findElementAt(9)
|
||||
val regList = PsiTreeUtil.getParentOfType(element, M68kRegisterListAddressingMode::class.java)!!
|
||||
assertThat(regList.registers).containsExactlyInAnyOrder(
|
||||
Register.D0, Register.D1, Register.D2, Register.D4,
|
||||
Register.A0, Register.A2, Register.A3, Register.A5,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun movem_register_list_with_data_address_wrapping(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||
testGoodSyntax(testCase, " movem.l d0-a6,-(sp)\n")
|
||||
val element = testCase.file.findElementAt(9)
|
||||
val regList = PsiTreeUtil.getParentOfType(element, M68kRegisterListAddressingMode::class.java)!!
|
||||
assertThat(regList.registers).containsExactlyInAnyOrder(
|
||||
Register.D0, Register.D1, Register.D2, Register.D3, Register.D4, Register.D5, Register.D6, Register.D7,
|
||||
Register.A0, Register.A1, Register.A2, Register.A3, Register.A4, Register.A5, Register.A6,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,12 +116,17 @@ internal class AddressingModesTest : AbstractParsingTest() {
|
||||
|
||||
@Test
|
||||
internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||
testGoodSyntax(testCase, " move.l usp,a0\n"
|
||||
+ " move.l a5,usp\n")
|
||||
testGoodSyntax(
|
||||
testCase, " move.l usp,a0\n"
|
||||
+ " move.l a5,usp\n"
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun complex_math_expression_in_displacement(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||
testGoodSyntax(testCase, " move.l -(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&$1f)(a0),(-(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&\$1f),a0,d0.l)\n")
|
||||
testGoodSyntax(
|
||||
testCase,
|
||||
" move.l -(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&$1f)(a0),(-(~(!!(+(1//~WIDTH^@123+3*4/2+(NARF%10|32!21))<<2)>>1)&\$1f),a0,d0.l)\n"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,11 @@ internal class ExpressionsTest : AbstractParsingTest() {
|
||||
testGoodSyntax(testCase, " dc.w *-.label\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun uppercase_hexadecimal_string(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||
testGoodSyntax(testCase, " move.l #\$DEADBEEF,d0\n")
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun if_with_single_equals_comparison(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) {
|
||||
testGoodSyntax(testCase, " IF DEBUG=1\n")
|
||||
|
||||
@@ -63,4 +63,15 @@ 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"""
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
+87
@@ -32,6 +32,93 @@ internal class M68kStructureViewTest : AbstractM68kTest() {
|
||||
.loopw
|
||||
main
|
||||
exit
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun macros_filter_works(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.configureByFile("basic_example.asm")
|
||||
myFixture.testStructureView {
|
||||
val tree = it.tree
|
||||
it.setActionActive(M68kStructureViewModel.MACROS_FILTER_ID, true)
|
||||
PlatformTestUtil.waitWhileBusy(tree)
|
||||
PlatformTestUtil.assertTreeEqual(
|
||||
tree, """-basic_example.asm
|
||||
PIC_WIDTH
|
||||
PIC_HEIGHT
|
||||
DEBUG_LEVEL
|
||||
entry
|
||||
-init
|
||||
.looph
|
||||
.loopw
|
||||
main
|
||||
exit
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun symbols_filter_works(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.configureByFile("basic_example.asm")
|
||||
myFixture.testStructureView {
|
||||
val tree = it.tree
|
||||
it.setActionActive(M68kStructureViewModel.SYMBOLS_FILTER_ID, true)
|
||||
PlatformTestUtil.waitWhileBusy(tree)
|
||||
PlatformTestUtil.assertTreeEqual(
|
||||
tree, """-basic_example.asm
|
||||
BLTHOGON
|
||||
BLTHOGOFF
|
||||
entry
|
||||
-init
|
||||
.looph
|
||||
.loopw
|
||||
main
|
||||
exit
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun global_labels_filter_works(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.configureByFile("basic_example.asm")
|
||||
myFixture.testStructureView {
|
||||
val tree = it.tree
|
||||
it.setActionActive(M68kStructureViewModel.GLOBAL_LABEL_FILTER_ID, true)
|
||||
PlatformTestUtil.waitWhileBusy(tree)
|
||||
PlatformTestUtil.assertTreeEqual(
|
||||
tree, """-basic_example.asm
|
||||
PIC_WIDTH
|
||||
PIC_HEIGHT
|
||||
DEBUG_LEVEL
|
||||
BLTHOGON
|
||||
BLTHOGOFF
|
||||
"""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
internal fun local_labels_filter_works(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||
myFixture.configureByFile("basic_example.asm")
|
||||
myFixture.testStructureView {
|
||||
val tree = it.tree
|
||||
it.setActionActive(M68kStructureViewModel.LOCAL_LABEL_FILTER_ID, true)
|
||||
PlatformTestUtil.waitWhileBusy(tree)
|
||||
PlatformTestUtil.assertTreeEqual(
|
||||
tree, """-basic_example.asm
|
||||
PIC_WIDTH
|
||||
PIC_HEIGHT
|
||||
DEBUG_LEVEL
|
||||
BLTHOGON
|
||||
BLTHOGOFF
|
||||
entry
|
||||
init
|
||||
main
|
||||
exit
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
+5
-4
@@ -177,9 +177,10 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
@@ -8,23 +8,28 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiWhiteSpace(' ')
|
||||
M68kRegisterListAddressingModeImpl(REGISTER_LIST_ADDRESSING_MODE)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d2')
|
||||
M68kRegisterRangeImpl(REGISTER_RANGE)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d2')
|
||||
PsiElement(M68kTokenType.OP_AR_DIV)('/')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d4')
|
||||
PsiElement(M68kTokenType.OP_AR_DIV)('/')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a2')
|
||||
PsiElement(M68kTokenType.OP_AR_DIV)('/')
|
||||
M68kRegisterRangeImpl(REGISTER_RANGE)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a2')
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.OP_AR_DIV)('/')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a4')
|
||||
PsiElement(M68kTokenType.AREG)('a5')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectPreDecAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_PRE_DEC_ADDRESSING_MODE)
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
Assembly File: a.asm
|
||||
PsiWhiteSpace(' ')
|
||||
M68kStatementImpl(STATEMENT)
|
||||
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||
M68kAsmOpImpl(ASM_OP)
|
||||
PsiElement(M68kTokenType.MNEMONIC)('movem')
|
||||
M68kOperandSizeImpl(OPERAND_SIZE)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiWhiteSpace(' ')
|
||||
M68kRegisterListAddressingModeImpl(REGISTER_LIST_ADDRESSING_MODE)
|
||||
M68kRegisterRangeImpl(REGISTER_RANGE)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a6')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectPreDecAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_PRE_DEC_ADDRESSING_MODE)
|
||||
PsiElement(M68kTokenType.OP_MINUS)('-')
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
+8
-6
@@ -21,8 +21,9 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
@@ -43,9 +44,10 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
+8
-6
@@ -20,10 +20,11 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kProgramCounterIndirectWithIndexOldAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE)
|
||||
@@ -43,7 +44,8 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
+8
-6
@@ -11,17 +11,19 @@ Assembly File: a.asm
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kProgramCounterIndirectWithIndexNewAddressingModeImpl(PROGRAM_COUNTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
PsiElement(M68kTokenType.ROUND_L)('(')
|
||||
PsiElement(M68kTokenType.PC)('pc')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
+8
-6
@@ -22,8 +22,9 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a0')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
@@ -45,9 +46,10 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a1')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d5')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
+8
-6
@@ -21,10 +21,11 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectWithIndexOldAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_OLD_ADDRESSING_MODE)
|
||||
@@ -45,7 +46,8 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a1')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
+8
-6
@@ -12,10 +12,11 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.REG_SP)('sp')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
M68kDataWidthImpl(DATA_WIDTH)
|
||||
PsiElement(M68kTokenType.OPSIZE_W)('.w')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterIndirectWithIndexNewAddressingModeImpl(ADDRESS_REGISTER_INDIRECT_WITH_INDEX_NEW_ADDRESSING_MODE)
|
||||
@@ -23,7 +24,8 @@ Assembly File: a.asm
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a1')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
M68kIndexRegisterImpl(INDEX_REGISTER)
|
||||
M68kAddressRegisterImpl(ADDRESS_REGISTER)
|
||||
PsiElement(M68kTokenType.AREG)('a3')
|
||||
PsiElement(M68kTokenType.ROUND_R)(')')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
@@ -0,0 +1,18 @@
|
||||
Assembly File: a.asm
|
||||
PsiWhiteSpace(' ')
|
||||
M68kStatementImpl(STATEMENT)
|
||||
M68kAsmInstructionImpl(ASM_INSTRUCTION)
|
||||
M68kAsmOpImpl(ASM_OP)
|
||||
PsiElement(M68kTokenType.MNEMONIC)('move')
|
||||
M68kOperandSizeImpl(OPERAND_SIZE)
|
||||
PsiElement(M68kTokenType.OPSIZE_L)('.l')
|
||||
PsiWhiteSpace(' ')
|
||||
M68kImmediateDataImpl(IMMEDIATE_DATA)
|
||||
PsiElement(M68kTokenType.HASH)('#')
|
||||
M68kLiteralExprImpl(LITERAL_EXPR)
|
||||
PsiElement(M68kTokenType.HEXADECIMAL)('$DEADBEEF')
|
||||
PsiElement(M68kTokenType.SEPARATOR)(',')
|
||||
M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE)
|
||||
M68kDataRegisterImpl(DATA_REGISTER)
|
||||
PsiElement(M68kTokenType.DREG)('d0')
|
||||
PsiElement(M68kTokenType.EOL)('\n')
|
||||
@@ -0,0 +1,15 @@
|
||||
Assembly File: a.asm
|
||||
PsiWhiteSpace('\n')
|
||||
M68kMacroDefinitionImpl(MACRO_DEFINITION)
|
||||
M68kMacroNameDefinitionImpl(MACRO_NAME_DEFINITION)
|
||||
PsiElement(M68kTokenType.MACRO_NAME)('structure')
|
||||
PsiElement(M68kTokenType.COLON)(':')
|
||||
PsiElement(M68kTokenType.MACRO_TAG)('macro')
|
||||
PsiWhiteSpace('\n')
|
||||
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
|
||||
PsiElement(M68kTokenType.MACRO_LINE)('\1:equ 0')
|
||||
PsiWhiteSpace('\n')
|
||||
M68kMacroPlainLineImpl(MACRO_PLAIN_LINE)
|
||||
PsiElement(M68kTokenType.MACRO_LINE)('soffset:set \2')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(M68kTokenType.MACRO_END_TAG)('\tendm')
|
||||
Reference in New Issue
Block a user