Courtesy of Yann:
Bugfix: Special registers for address mode matching only worked with lower case register names. Bugfix: movem with pc-relative mode was missing for weird immediate mode. Bugfix: btst with pc-relative and weird immediate mode was missing. Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors.
This commit is contained in:
		
							parent
							
								
									89bd964fe7
								
							
						
					
					
						commit
						3bb6165a58
					
				| @ -148,6 +148,13 @@ are appreciated. They really are, because they do keep me motivated to continue | ||||
| 
 | ||||
| ## Changelog | ||||
| 
 | ||||
| ### V0.7 (unreleased) | ||||
| 
 | ||||
| - Bugfix: `btst` with pc-relative and weird immediate mode was missing (courtesy of Yann). | ||||
| - Bugfix: `movem` with pc-relative mode was missing for weird immediate mode (courtesy of Yann). | ||||
| - Bugfix: Special registers for address mode matching only worked with lower case register names (courtesy of Yann). | ||||
| - Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors (courtesy of Yann). | ||||
| 
 | ||||
| ### V0.6 (09-Aug-21) | ||||
| 
 | ||||
| - Enhancement: `opt` and several other directives (`printt`, `fail` etc.) no longer causes a syntax error when unquoted. | ||||
|  | ||||
							
								
								
									
										24
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								build.gradle
									
									
									
									
									
								
							| @ -7,7 +7,7 @@ plugins { | ||||
| } | ||||
| 
 | ||||
| group = 'de.platon42' | ||||
| version = '0.6' | ||||
| version = '0.7' | ||||
| sourceCompatibility = "1.8" | ||||
| targetCompatibility = "1.8" | ||||
| 
 | ||||
| @ -57,6 +57,13 @@ runPluginVerifier { | ||||
| 
 | ||||
| patchPluginXml { | ||||
|     setChangeNotes(""" | ||||
|   <h4>V0.7 (unreleased)</h4> | ||||
|     <ul> | ||||
|       <li>Bugfix: 'btst' with pc-relative and weird immediate mode was missing (courtesy of Yann). | ||||
|       <li>Bugfix: 'movem' with pc-relative mode was missing for weird immediate mode (courtesy of Yann). | ||||
|       <li>Bugfix: Special registers for address mode matching only worked with lower case register names (courtesy of Yann). | ||||
|       <li>Enhancement: Assembler syntax with implicit immediate 1 for shifts and rotations no longer cause syntax errors (courtesy of Yann). | ||||
|     </ul> | ||||
|   <h4>V0.6 (09-Aug-21)</h4> | ||||
|     <ul> | ||||
|       <li>Enhancement: 'opt' and several other directives ('printt', 'fail' etc.) no longer causes a syntax error when unquoted. | ||||
| @ -71,7 +78,7 @@ patchPluginXml { | ||||
|     <ul> | ||||
|       <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: 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. | ||||
| @ -79,19 +86,6 @@ patchPluginXml { | ||||
|       <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.4 (03-Aug-21)</h4> | ||||
|     <ul> | ||||
|       <li>Notice: Due to major new API use, this plugin no longer works on IDEs >=2019.3.1, but rather requires >=2020.3. | ||||
|       <li>Enhancement: Added Structure View filters. | ||||
|       <li>New: Added inspection to validate the correctness of a MC68000 instruction regarding operation size and address modes. | ||||
|       <li>Bugfix: Added several missing assembler directives (opt, machine, etc.). | ||||
|       <li>Bugfix: Uppercase hexadecimal literals were not parsed (JFlex bug?). | ||||
|       <li>Bugfix: Interpretation of register lists was wrong in BNF. | ||||
|       <li>New: Added Documentation Provider for symbol definitions (shows assigned declaration). | ||||
|       <li>New: Added Documentation Provider for mnemonics (simple version, generated out of ISA information). | ||||
|       <li>Bugfix: Macro definitions with colons and without space supported (as found in P61a source). | ||||
|       <li>New: When asking for documentation on registers, a code flow analysis is done. Cool stuff! | ||||
|     </ul> | ||||
|   <p>Full changelog available at <a href="https://github.com/chrisly42/mc68000-asm-plugin#changelog">Github project site</a>.</p> | ||||
| """) | ||||
| } | ||||
|  | ||||
| @ -44,7 +44,7 @@ enum class AddressMode(val description: String, val syntax: String) { | ||||
|     PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT("program counter indirect with displacement", "(d16,PC)"), | ||||
|     ADDRESS_REGISTER_INDIRECT_WITH_INDEX("address register indirect with index", "(d8,An,Xn)"), | ||||
|     PROGRAM_COUNTER_INDIRECT_WITH_INDEX("program counter indirect with index", "(d8,PC,Xn)"), | ||||
|     SPECIAL_REGISTER_DIRECT("special register", "ccr|usp|vbr"), | ||||
|     SPECIAL_REGISTER_DIRECT("special register", "sr|ccr|usp|vbr"), | ||||
|     REGISTER_LIST("register list", "list"), | ||||
|     IMMEDIATE_DATA("immediate", "#<xxx>"), | ||||
|     ABSOLUTE_ADDRESS("absolute short/long", "(xxx).w|l") | ||||
| @ -202,6 +202,18 @@ object M68kIsa { | ||||
|         AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX, | ||||
|     ) | ||||
| 
 | ||||
|     private val ALL_EXCEPT_AREG_AND_DREG = setOf( | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT, | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC, | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT_PRE_DEC, | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT, | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX, | ||||
|         AddressMode.ABSOLUTE_ADDRESS, | ||||
|         AddressMode.IMMEDIATE_DATA, | ||||
|         AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT, | ||||
|         AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX, | ||||
|     ) | ||||
| 
 | ||||
|     private val INDIRECT_MODES = setOf( | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT, | ||||
|         AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC, | ||||
| @ -256,33 +268,39 @@ object M68kIsa { | ||||
|     private val ASD_LSD_MODES = listOf( | ||||
|         AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("*****")), | ||||
|         AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")), | ||||
|         AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")), | ||||
|         // not an official address mode, but supported by assembler (implicit #1) | ||||
|         AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("*****")) | ||||
|     ) | ||||
| 
 | ||||
|     private val ROD_MODES = listOf( | ||||
|         AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("-**0*")), | ||||
|         AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")), | ||||
|         AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")), | ||||
|         // not an official address mode, but supported by assembler (implicit #1) | ||||
|         AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("-**0*")), | ||||
|     ) | ||||
| 
 | ||||
|     private val ROXD_MODES = listOf( | ||||
|         AllowedAdrMode(DREG_ONLY, DREG_ONLY, modInfo = RWM_READ_OP1_OPSIZE or RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, modInfo = RWM_MODIFY_OP2_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")), | ||||
|         AllowedAdrMode(INDIRECT_MODES, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")), | ||||
|         AllowedAdrMode(INDIRECT_MODES, null, size = OP_SIZE_W, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")), | ||||
|         // not an official address mode, but supported by assembler (implicit #1) | ||||
|         AllowedAdrMode(DREG_ONLY, null, modInfo = RWM_MODIFY_OP1_OPSIZE, affectedCc = cc("***0*"), testedCc = cc("?----")), | ||||
|     ) | ||||
| 
 | ||||
|     private val BCHG_BCLR_BSET_MODES = listOf( | ||||
|         AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_L, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_MODIFY_OP2_B, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_MODIFY_OP2_L, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_MODIFY_OP2_B, affectedCc = cc("--*--")), | ||||
|     ) | ||||
| 
 | ||||
|     private val BTST_MODES = listOf( | ||||
|         AllowedAdrMode(DREG_ONLY, DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_L, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(DREG_ONLY, INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(DREG_ONLY, ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_READ_OP1_B or RWM_READ_OP2_B, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), DREG_ONLY, OP_SIZE_L, modInfo = RWM_READ_OP2_L, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), INDIRECT_MODES, OP_SIZE_B, modInfo = RWM_READ_OP2_B, affectedCc = cc("--*--")), | ||||
|         AllowedAdrMode(setOf(AddressMode.IMMEDIATE_DATA), ALL_EXCEPT_AREG_AND_DREG, OP_SIZE_B, modInfo = RWM_READ_OP2_B, affectedCc = cc("--*--")), | ||||
|     ) | ||||
| 
 | ||||
|     private val conditionCodes = | ||||
| @ -354,7 +372,9 @@ object M68kIsa { | ||||
|                         AddressMode.ADDRESS_REGISTER_INDIRECT_POST_INC, | ||||
|                         AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_DISPLACEMENT, | ||||
|                         AddressMode.ADDRESS_REGISTER_INDIRECT_WITH_INDEX, | ||||
|                         AddressMode.ABSOLUTE_ADDRESS | ||||
|                         AddressMode.ABSOLUTE_ADDRESS, | ||||
|                         AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_DISPLACEMENT, | ||||
|                         AddressMode.PROGRAM_COUNTER_INDIRECT_WITH_INDEX | ||||
|                     ), | ||||
|                     setOf(AddressMode.IMMEDIATE_DATA), | ||||
|                     OP_SIZE_WL, | ||||
| @ -944,5 +964,5 @@ object M68kIsa { | ||||
|     private fun isAddressModeMatching(am: AllowedAdrMode, op1: AddressMode?, op2: AddressMode?, specialReg: String?) = | ||||
|         ((((op1 == null) && (am.op1 == null)) || am.op1?.contains(op1) ?: false) | ||||
|                 && (((op2 == null) && (am.op2 == null)) || am.op2?.contains(op2) ?: false) | ||||
|                 && ((specialReg == null) || (specialReg == am.specialReg))) | ||||
|                 && ((specialReg == null) || (specialReg.equals(am.specialReg, true)))) | ||||
| } | ||||
| @ -16,7 +16,7 @@ | ||||
| 
 | ||||
|     <extensions defaultExtensionNs="com.intellij"> | ||||
|         <fileType name="MC68000 Assembler" implementationClass="de.platon42.intellij.plugins.m68k.M68kFileType" | ||||
|                   fieldName="INSTANCE" language="MC68000" extensions="asm;ASM;s;S;i"/> | ||||
|                   fieldName="INSTANCE" language="MC68000" extensions="asm;s;i"/> | ||||
|         <lang.parserDefinition language="MC68000" | ||||
|                                implementationClass="de.platon42.intellij.plugins.m68k.parser.M68kParserDefinition"/> | ||||
|         <lang.syntaxHighlighterFactory language="MC68000" | ||||
| @ -47,7 +47,7 @@ | ||||
|         <stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kGlobalLabelStubIndex"/> | ||||
|         <stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kSymbolDefinitionStubIndex"/> | ||||
|         <stubIndex implementation="de.platon42.intellij.plugins.m68k.stubs.M68kMacroDefinitionStubIndex"/> | ||||
|         <psi.referenceContributor implementation="de.platon42.intellij.plugins.m68k.refs.M68kReferenceContributor"/> | ||||
|         <psi.referenceContributor language="MC68000" 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"/> | ||||
|         <include.provider implementation="de.platon42.intellij.plugins.m68k.scanner.M68kIncludeFileProvider"/> | ||||
|  | ||||
| @ -87,6 +87,11 @@ internal class AddressingModesTest : AbstractParsingTest() { | ||||
|         testGoodSyntax(testCase, " move.l 4.w,a6\n") | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     internal fun btst_quirk(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) { | ||||
|         testGoodSyntax(testCase, " btst #5,#42\n btst d0,#42") | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     internal fun movem_register_list(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) { | ||||
|         testGoodSyntax(testCase, " movem.l d0-d2/d4/a0/a2-a3/a5,-(sp)\n") | ||||
| @ -118,7 +123,7 @@ internal class AddressingModesTest : AbstractParsingTest() { | ||||
|     internal fun special_register_move(@MyTestCase testCase: ParsingTestExtension.IParsingTestCase) { | ||||
|         testGoodSyntax( | ||||
|             testCase, " move.l usp,a0\n" | ||||
|                     + " move.l a5,usp\n" | ||||
|                     + " move.l a5,USP\n" | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										31
									
								
								src/test/resources/parser/addressingmodes/btst_quirk.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/test/resources/parser/addressingmodes/btst_quirk.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| Assembly File: a.asm | ||||
|   PsiWhiteSpace(' ') | ||||
|   M68kStatementImpl(STATEMENT) | ||||
|     M68kAsmInstructionImpl(ASM_INSTRUCTION) | ||||
|       M68kAsmOpImpl(ASM_OP) | ||||
|         PsiElement(M68kTokenType.MNEMONIC)('btst') | ||||
|       PsiWhiteSpace(' ') | ||||
|       M68kImmediateDataImpl(IMMEDIATE_DATA) | ||||
|         PsiElement(M68kTokenType.HASH)('#') | ||||
|         M68kLiteralExprImpl(LITERAL_EXPR) | ||||
|           PsiElement(M68kTokenType.DECIMAL)('5') | ||||
|       PsiElement(M68kTokenType.SEPARATOR)(',') | ||||
|       M68kImmediateDataImpl(IMMEDIATE_DATA) | ||||
|         PsiElement(M68kTokenType.HASH)('#') | ||||
|         M68kLiteralExprImpl(LITERAL_EXPR) | ||||
|           PsiElement(M68kTokenType.DECIMAL)('42') | ||||
|   PsiElement(M68kTokenType.EOL)('\n') | ||||
|   PsiWhiteSpace(' ') | ||||
|   M68kStatementImpl(STATEMENT) | ||||
|     M68kAsmInstructionImpl(ASM_INSTRUCTION) | ||||
|       M68kAsmOpImpl(ASM_OP) | ||||
|         PsiElement(M68kTokenType.MNEMONIC)('btst') | ||||
|       PsiWhiteSpace(' ') | ||||
|       M68kDataRegisterDirectAddressingModeImpl(DATA_REGISTER_DIRECT_ADDRESSING_MODE) | ||||
|         M68kDataRegisterImpl(DATA_REGISTER) | ||||
|           PsiElement(M68kTokenType.DREG)('d0') | ||||
|       PsiElement(M68kTokenType.SEPARATOR)(',') | ||||
|       M68kImmediateDataImpl(IMMEDIATE_DATA) | ||||
|         PsiElement(M68kTokenType.HASH)('#') | ||||
|         M68kLiteralExprImpl(LITERAL_EXPR) | ||||
|           PsiElement(M68kTokenType.DECIMAL)('42') | ||||
| @ -29,5 +29,5 @@ Assembly File: a.asm | ||||
|       PsiElement(M68kTokenType.SEPARATOR)(',') | ||||
|       M68kSpecialRegisterDirectAddressingModeImpl(SPECIAL_REGISTER_DIRECT_ADDRESSING_MODE) | ||||
|         M68kSpecialRegisterImpl(SPECIAL_REGISTER) | ||||
|           PsiElement(M68kTokenType.REG_USP)('usp') | ||||
|           PsiElement(M68kTokenType.REG_USP)('USP') | ||||
|   PsiElement(M68kTokenType.EOL)('\n') | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user