Added M68kAddressRegisterWordAccessInspection
This commit is contained in:
parent
84eb1eab69
commit
a3f979b48b
15
README.md
15
README.md
@ -84,6 +84,17 @@ optimize the order of execution.
|
|||||||
Points out unresolved references such for global and local labels, macros or symbols. Right now, missing symbol and global label references are shown only as
|
Points out unresolved references such for global and local labels, macros or symbols. Right now, missing symbol and global label references are shown only as
|
||||||
weak warnings as missing macro evaluation will not resolve symbols defined via `STRUCT` macros.
|
weak warnings as missing macro evaluation will not resolve symbols defined via `STRUCT` macros.
|
||||||
|
|
||||||
|
#### M68kAddressRegisterWordAccessInspection - Suspicious word access to address register
|
||||||
|
|
||||||
|
Warns on `movea.w` to address registers which is often a typo and takes ages to find and fix.
|
||||||
|
Of course there are legal intentional uses of this instruction that sign extends the word
|
||||||
|
to a long word, or using it as a temporary register or for index purposes.
|
||||||
|
|
||||||
|
Also warns on `cmpa.w` with address register as second operand (there are some clever ways
|
||||||
|
using this, such as using `cmpa.w ax,ax` to see if a value is between $ffff8000 and $7fff).
|
||||||
|
|
||||||
|
Third instruction checked is `tst.w` on address registers for 68020+.
|
||||||
|
|
||||||
### Documentation provider
|
### Documentation provider
|
||||||
|
|
||||||
#### M68kSymbolDefinition
|
#### M68kSymbolDefinition
|
||||||
@ -166,6 +177,10 @@ are appreciated. It really is keeping me motivated to continue development.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### V0.11 (unreleased)
|
||||||
|
|
||||||
|
- New: Added M68kAddressRegisterWordAccessInspection to find suspicious uses of address registers.
|
||||||
|
|
||||||
### V0.10 (20-Feb-24)
|
### V0.10 (20-Feb-24)
|
||||||
|
|
||||||
- Decided to release some features that have been sitting on my harddrive for almost two years, but never got released,
|
- Decided to release some features that have been sitting on my harddrive for almost two years, but never got released,
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.inspections
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.InspectionManager
|
||||||
|
import com.intellij.codeInspection.ProblemDescriptor
|
||||||
|
import com.intellij.codeInspection.ProblemHighlightType
|
||||||
|
import de.platon42.intellij.plugins.m68k.asm.AddressMode
|
||||||
|
import de.platon42.intellij.plugins.m68k.asm.M68kIsa.findMatchingInstructions
|
||||||
|
import de.platon42.intellij.plugins.m68k.asm.OP_SIZE_W
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kAddressModeUtil
|
||||||
|
import de.platon42.intellij.plugins.m68k.psi.M68kAsmInstruction
|
||||||
|
import de.platon42.intellij.plugins.m68k.utils.M68kIsaUtil.findExactIsaDataAndAllowedAdrModeForInstruction
|
||||||
|
|
||||||
|
class M68kAddressRegisterWordAccessInspection : AbstractBaseM68kLocalInspectionTool() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DISPLAY_NAME = "Word access to address register"
|
||||||
|
|
||||||
|
private const val ADDR_REG_WORD_ACCESS_MSG_TEMPLATE = "Suspicious %s %s address register"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDisplayName() = DISPLAY_NAME
|
||||||
|
|
||||||
|
override fun checkAsmInstruction(asmInstruction: M68kAsmInstruction, manager: InspectionManager, isOnTheFly: Boolean): Array<ProblemDescriptor>? {
|
||||||
|
val asmOp = asmInstruction.asmOp
|
||||||
|
if (asmOp.opSize != OP_SIZE_W) return emptyArray()
|
||||||
|
|
||||||
|
val isaDataCandidates = findMatchingInstructions(asmOp.mnemonic)
|
||||||
|
if (isaDataCandidates.isEmpty()) return emptyArray()
|
||||||
|
val (isaData, adrMode) = findExactIsaDataAndAllowedAdrModeForInstruction(asmInstruction) ?: return emptyArray()
|
||||||
|
|
||||||
|
return when (isaData.mnemonic) {
|
||||||
|
"movea" -> arrayOf(
|
||||||
|
manager.createProblemDescriptor(
|
||||||
|
asmInstruction,
|
||||||
|
asmInstruction,
|
||||||
|
ADDR_REG_WORD_ACCESS_MSG_TEMPLATE.format(isaData.mnemonic, "word write to"),
|
||||||
|
ProblemHighlightType.WARNING,
|
||||||
|
isOnTheFly
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
"cmpa" -> arrayOf(
|
||||||
|
manager.createProblemDescriptor(
|
||||||
|
asmInstruction,
|
||||||
|
asmInstruction,
|
||||||
|
ADDR_REG_WORD_ACCESS_MSG_TEMPLATE.format(isaData.mnemonic, "comparing with word-sized"),
|
||||||
|
ProblemHighlightType.WARNING,
|
||||||
|
isOnTheFly
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
"tst" -> if (M68kAddressModeUtil.getAddressModeForType(asmInstruction.addressingModeList.getOrNull(0)) == AddressMode.ADDRESS_REGISTER_DIRECT) {
|
||||||
|
arrayOf(
|
||||||
|
manager.createProblemDescriptor(
|
||||||
|
asmInstruction,
|
||||||
|
asmInstruction,
|
||||||
|
ADDR_REG_WORD_ACCESS_MSG_TEMPLATE.format(isaData.mnemonic, "with word-sized"),
|
||||||
|
ProblemHighlightType.WARNING,
|
||||||
|
isOnTheFly
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
emptyArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> emptyArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,22 +12,26 @@ import de.platon42.intellij.plugins.m68k.psi.utils.M68kLookupUtil
|
|||||||
class M68kGlobalLabelSymbolCompletionContributor : CompletionContributor() {
|
class M68kGlobalLabelSymbolCompletionContributor : CompletionContributor() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val REGISTER_SUGGESTIONS: List<LookupElement> =
|
val REGS = listOf(
|
||||||
listOf(
|
|
||||||
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
|
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
|
||||||
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
|
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
|
||||||
"pc"
|
"pc"
|
||||||
)
|
)
|
||||||
.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
|
val REGSET = REGS.toSet()
|
||||||
|
val REGISTER_SUGGESTIONS: List<LookupElement> =
|
||||||
|
REGS.map { PrioritizedLookupElement.withPriority(LookupElementBuilder.create(it).withIcon(M68kIcons.REGISTER).withBoldness(true), 2.0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.SYMBOL), object : CompletionProvider<CompletionParameters>() {
|
extend(CompletionType.BASIC, PlatformPatterns.psiElement(M68kTypes.SYMBOL), object : CompletionProvider<CompletionParameters>() {
|
||||||
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
|
override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, resultSet: CompletionResultSet) {
|
||||||
resultSet.addAllElements(REGISTER_SUGGESTIONS)
|
resultSet.addAllElements(REGISTER_SUGGESTIONS)
|
||||||
|
val prefix = resultSet.prefixMatcher.prefix.lowercase()
|
||||||
|
if (!(prefix == "a" || prefix == "d" || REGSET.contains(prefix))) {
|
||||||
resultSet.addAllElements(M68kLookupUtil.findAllGlobalLabels(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
|
resultSet.addAllElements(M68kLookupUtil.findAllGlobalLabels(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
|
||||||
resultSet.addAllElements(M68kLookupUtil.findAllSymbolDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
|
resultSet.addAllElements(M68kLookupUtil.findAllSymbolDefinitions(parameters.originalFile.project).map(LookupElementBuilder::createWithIcon))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -77,6 +77,9 @@
|
|||||||
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnresolvedReferenceInspection"
|
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kUnresolvedReferenceInspection"
|
||||||
displayName="Unresolved label/symbol/macro reference" groupName="M68k"
|
displayName="Unresolved label/symbol/macro reference" groupName="M68k"
|
||||||
enabledByDefault="true" level="WARNING"/>
|
enabledByDefault="true" level="WARNING"/>
|
||||||
|
<localInspection implementationClass="de.platon42.intellij.plugins.m68k.inspections.M68kAddressRegisterWordAccessInspection"
|
||||||
|
displayName="Suspicious word access to address register" groupName="M68k"
|
||||||
|
enabledByDefault="true" level="WARNING"/>
|
||||||
|
|
||||||
<projectService serviceImplementation="de.platon42.intellij.plugins.m68k.settings.M68kProjectSettings"/>
|
<projectService serviceImplementation="de.platon42.intellij.plugins.m68k.settings.M68kProjectSettings"/>
|
||||||
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package de.platon42.intellij.plugins.m68k.inspections
|
||||||
|
|
||||||
|
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||||
|
import de.platon42.intellij.jupiter.MyFixture
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
internal class M68kAddressRegisterWordAccessInspectionTest : AbstractInspectionTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun shows_warning_on_movea_word_sized(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kAddressRegisterWordAccessInspection::class.java)
|
||||||
|
myFixture.configureByText("wordaccess.asm", " move.w d0,a0")
|
||||||
|
assertHighlightings(myFixture, 1, "Suspicious movea word write to address register")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun shows_warning_on_cmpa_word_sized(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kAddressRegisterWordAccessInspection::class.java)
|
||||||
|
myFixture.configureByText("wordaccess.asm", " cmp.w d0,a0")
|
||||||
|
assertHighlightings(myFixture, 1, "Suspicious cmpa comparing with word-sized address register")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
internal fun shows_warning_on_tst_with_word_sized_address_register(@MyFixture myFixture: CodeInsightTestFixture) {
|
||||||
|
myFixture.enableInspections(M68kAddressRegisterWordAccessInspection::class.java)
|
||||||
|
myFixture.configureByText("wordaccess.asm", " tst.w a0")
|
||||||
|
assertHighlightings(myFixture, 1, "Suspicious tst with word-sized address register")
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user