From a1a561fe494e4b165482c2f0404aef5ea19b1c9f Mon Sep 17 00:00:00 2001 From: Michael Billington Date: Sat, 5 Feb 2022 16:36:28 +1100 Subject: [PATCH] add auto-complete for mnemonics, actions for switching CPU target, annotation for opcodes which are unavailable on the current target --- build.gradle | 6 +- build.sh | 2 +- src/main/java/org/ca65/Asm.bnf | 5 +- .../AsmMnemonicCompletionContributor.java | 43 +++++ .../ChangeProjectCpuIntentionAction.java | 48 ++++++ .../UnsupportedMnemonicAnnotator.java | 40 +++++ .../org/ca65/config/AsmConfiguration.java | 48 ++++++ src/main/java/org/ca65/helpers/Cpu.java | 13 ++ .../java/org/ca65/helpers/MnemonicHelper.java | 148 ++++++++++++++++++ .../java/org/ca65/helpers/MnemonicInfo.java | 11 ++ src/main/resources/META-INF/plugin.xml | 4 +- .../messages/Asm6502Bundle.properties | 3 + .../Generic 6502 Project/.idea/workspace.xml | 17 -- .../root0/Generic 6502 Project.iml | 8 + .../Generic 6502 Project/{ => root0}/Makefile | 0 .../{ => root0}/hello.cfg | 0 .../Generic 6502 Project/{ => root0}/hello.s | 1 + 17 files changed, 375 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/ca65/AsmMnemonicCompletionContributor.java create mode 100644 src/main/java/org/ca65/action/ChangeProjectCpuIntentionAction.java create mode 100644 src/main/java/org/ca65/annotator/UnsupportedMnemonicAnnotator.java create mode 100644 src/main/java/org/ca65/config/AsmConfiguration.java create mode 100644 src/main/java/org/ca65/helpers/Cpu.java create mode 100644 src/main/java/org/ca65/helpers/MnemonicHelper.java create mode 100644 src/main/java/org/ca65/helpers/MnemonicInfo.java delete mode 100644 templates/Generic 6502 Project/.idea/workspace.xml create mode 100644 templates/Generic 6502 Project/root0/Generic 6502 Project.iml rename templates/Generic 6502 Project/{ => root0}/Makefile (100%) rename templates/Generic 6502 Project/{ => root0}/hello.cfg (100%) rename templates/Generic 6502 Project/{ => root0}/hello.s (99%) diff --git a/build.gradle b/build.gradle index fce6686..46c415e 100644 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,11 @@ runPluginVerifier { } patchPluginXml { - changeNotes = """This change adds intention actions for converting numeric literals between hexadecimal, decimal and binary representations.""" + changeNotes = """This change adds intention actions for converting numeric literals between hexadecimal, decimal and binary representations. + +It also adds a completion helper for assembly language mnemonics, an inspection to indicate when unsupported mnemonics are used, and a quick-fix for switching the CPU target to one which includes the unsupported mnemonic. + +The 'Generic 6502 Project' template has also been improved.""" sinceBuild = '211.6693' } diff --git a/build.sh b/build.sh index de66435..c17f66c 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/bin/bash set -exu -o pipefail rm -Rf build src/main/gen src/main/resources/projectTemplates/*.zip -(cd templates && zip --recurse-paths "../src/main/resources/projectTemplates/Generic 6502 Project.zip" "Generic 6502 Project/") +(cd "templates/Generic 6502 Project" && zip --recurse-paths "../../src/main/resources/projectTemplates/Generic 6502 Project.zip" root0/ .idea/) ./gradlew generateAsmLexer generateAsmParser verifyPlugin buildPlugin ./gradlew runPluginVerifier diff --git a/src/main/java/org/ca65/Asm.bnf b/src/main/java/org/ca65/Asm.bnf index 2a78c6f..3f43a64 100644 --- a/src/main/java/org/ca65/Asm.bnf +++ b/src/main/java/org/ca65/Asm.bnf @@ -32,16 +32,17 @@ identifierdef ::= identifierr { imports ::= IMPORT_KEYWORD identifierdef ( COMMA identifierdef )* dotexpr ::= DOT_KEYWORD expr macro ::= IDENTIFIER expr -llabel ::= MNEMONIC expr? +llabel ::= instruction_mnemonic expr? define_constant_numeric ::= identifierdef ( EQUALS ) expr define_constant_label ::= identifierdef ( COLON_EQUALS ) expr expr ::= anything* -anything ::= (MNEMONIC|numeric_literal|STRING_LITERAL|DOT_KEYWORD|identifierr|LABEL|EQUALS|COLON_EQUALS|COMMA|REGISTER|CHAR_LITERAL|LPAREN|RPAREN|OR|LSHIFT|RSHIFT|AND|CONSTEXPR|SHORTLABEL_REF|local_label_rref|SHORTLABEL|HIBYTE|LOBYTE|BOOLOR|BOOLAND|NOT|DIV|MUL|ADD|SUB|XOR|SCOPE_ACCESS) +anything ::= (instruction_mnemonic|numeric_literal|STRING_LITERAL|DOT_KEYWORD|identifierr|LABEL|EQUALS|COLON_EQUALS|COMMA|REGISTER|CHAR_LITERAL|LPAREN|RPAREN|OR|LSHIFT|RSHIFT|AND|CONSTEXPR|SHORTLABEL_REF|local_label_rref|SHORTLABEL|HIBYTE|LOBYTE|BOOLOR|BOOLAND|NOT|DIV|MUL|ADD|SUB|XOR|SCOPE_ACCESS) numeric_literal ::= INT_LITERAL +instruction_mnemonic ::= MNEMONIC identifierr ::= IDENTIFIER { mixin="org.ca65.psi.impl.AsmIdentifierImpl" diff --git a/src/main/java/org/ca65/AsmMnemonicCompletionContributor.java b/src/main/java/org/ca65/AsmMnemonicCompletionContributor.java new file mode 100644 index 0000000..0b406f3 --- /dev/null +++ b/src/main/java/org/ca65/AsmMnemonicCompletionContributor.java @@ -0,0 +1,43 @@ +package org.ca65; + +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.util.ProcessingContext; +import org.ca65.config.AsmConfiguration; +import org.ca65.helpers.Cpu; +import org.ca65.helpers.MnemonicHelper; +import org.ca65.helpers.MnemonicInfo; +import org.ca65.psi.AsmTypes; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.Set; + +import static com.intellij.patterns.PlatformPatterns.psiElement; +import static org.ca65.helpers.MnemonicHelper.allMnemnonics; + +public class AsmMnemonicCompletionContributor extends CompletionContributor { + public AsmMnemonicCompletionContributor() { + // Offer to auto-complete mnemonics at the start of a blank line + extend(CompletionType.BASIC, psiElement().afterLeaf(psiElement(AsmTypes.EOL_WS)), new MnemonicCompletionProvider()); + } +} + +class MnemonicCompletionProvider extends CompletionProvider { + public void addCompletions(@NotNull CompletionParameters parameters, + @NotNull ProcessingContext context, + @NotNull CompletionResultSet resultSet) { + Color mnemonicColor = AsmSyntaxHighlighter.MNEMONIC.getDefaultAttributes().getForegroundColor(); + Cpu projectCpu = AsmConfiguration.getInstance(parameters.getPosition().getProject()).getCpu(); + Set mnemonicsToShow = MnemonicHelper.getMnemonicsForCpu(projectCpu); + for(MnemonicInfo completionMnemonic : allMnemnonics) { + if(!mnemonicsToShow.contains(completionMnemonic.mnemnonic)) { + // Skip mnemonics which aren't valid for this CPU. + continue; + } + resultSet.addElement(LookupElementBuilder.create(completionMnemonic.mnemnonic) + .withItemTextForeground(mnemonicColor) + .withTailText(" " + completionMnemonic.description)); + } + } +} diff --git a/src/main/java/org/ca65/action/ChangeProjectCpuIntentionAction.java b/src/main/java/org/ca65/action/ChangeProjectCpuIntentionAction.java new file mode 100644 index 0000000..4ec41f5 --- /dev/null +++ b/src/main/java/org/ca65/action/ChangeProjectCpuIntentionAction.java @@ -0,0 +1,48 @@ +package org.ca65.action; + +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.util.IntentionFamilyName; +import com.intellij.codeInspection.util.IntentionName; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import org.ca65.Asm6502Bundle; +import org.ca65.config.AsmConfiguration; +import org.ca65.helpers.Cpu; +import org.jetbrains.annotations.NotNull; + +public class ChangeProjectCpuIntentionAction implements IntentionAction { + private final Cpu cpu; + + public ChangeProjectCpuIntentionAction(Cpu cpu) { + this.cpu = cpu; + } + + @Override + public @IntentionName @NotNull String getText() { + return Asm6502Bundle.message("INTN.change.cpu", cpu.name); + } + + @Override + public @NotNull @IntentionFamilyName String getFamilyName() { + return Asm6502Bundle.message("INTN.NAME.change.cpu"); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return true; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + AsmConfiguration.getInstance(project).setCpu(this.cpu); + DaemonCodeAnalyzer.getInstance(project).restart(); + } + + @Override + public boolean startInWriteAction() { + return false; + } +} diff --git a/src/main/java/org/ca65/annotator/UnsupportedMnemonicAnnotator.java b/src/main/java/org/ca65/annotator/UnsupportedMnemonicAnnotator.java new file mode 100644 index 0000000..d41fb85 --- /dev/null +++ b/src/main/java/org/ca65/annotator/UnsupportedMnemonicAnnotator.java @@ -0,0 +1,40 @@ +package org.ca65.annotator; + +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.lang.annotation.AnnotationBuilder; +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.psi.PsiElement; +import org.ca65.action.ChangeProjectCpuIntentionAction; +import org.ca65.config.AsmConfiguration; +import org.ca65.helpers.Cpu; +import org.ca65.helpers.MnemonicHelper; +import org.ca65.psi.AsmInstructionMnemonic; +import org.jetbrains.annotations.NotNull; + +public class UnsupportedMnemonicAnnotator implements Annotator { + @Override + public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) { + // Ensure the Psi Element is an expression + if (!(element instanceof AsmInstructionMnemonic)) { + return; + } + String thisMnemonic = element.getText().toLowerCase(); + Cpu projectCpu = AsmConfiguration.getInstance(element.getProject()).getCpu(); + if (MnemonicHelper.getMnemonicsForCpu(projectCpu).contains(thisMnemonic)) { + return; // All is good + } + AnnotationBuilder builder = holder.newAnnotation(HighlightSeverity.ERROR, "The '" + thisMnemonic + "' instruction is not available on the " + projectCpu.name + " CPU") + .range(element.getTextRange()) + .highlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); + // Suggest alternative CPU setting if we have another CPU config which contains this + if (MnemonicHelper.getMnemonicsForCpu(Cpu.CPU_65C02).contains(thisMnemonic)) { + builder = builder.withFix(new ChangeProjectCpuIntentionAction(Cpu.CPU_65C02)); + } else if(MnemonicHelper.getMnemonicsForCpu(Cpu.CPU_65C816).contains(thisMnemonic)) { + // Suggest 65C816 only if instruction is not available on 65C02! + builder = builder.withFix(new ChangeProjectCpuIntentionAction(Cpu.CPU_65C816)); + } + builder.create(); + } +} diff --git a/src/main/java/org/ca65/config/AsmConfiguration.java b/src/main/java/org/ca65/config/AsmConfiguration.java new file mode 100644 index 0000000..2b56d76 --- /dev/null +++ b/src/main/java/org/ca65/config/AsmConfiguration.java @@ -0,0 +1,48 @@ +package org.ca65.config; + +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.project.Project; +import com.intellij.util.xmlb.annotations.XMap; +import org.ca65.helpers.Cpu; +import org.jetbrains.annotations.NotNull; + +@State(name = "AsmConfiguration", + storages = @Storage("asm_6502.xml")) +public class AsmConfiguration implements PersistentStateComponent { + public static class State { + @XMap(entryTagName = "cpu") + public String cpu; + } + + private AsmConfiguration.State myState = new State(); + + public static AsmConfiguration getInstance(Project project) { + return project.getService(AsmConfiguration.class); + } + + @Override + public AsmConfiguration.State getState() { + return myState; + } + + @Override + public void loadState(@NotNull AsmConfiguration.State state) { + myState = state; + } + + public Cpu getCpu() { + for(Cpu item : Cpu.values()) { + if(item.toString().equals(this.myState.cpu)) { + return item; + } + } + // Default to classic 6502 + return Cpu.CPU_6502; + } + + public void setCpu(Cpu newCpu) { + this.myState.cpu = newCpu.toString(); + } +} diff --git a/src/main/java/org/ca65/helpers/Cpu.java b/src/main/java/org/ca65/helpers/Cpu.java new file mode 100644 index 0000000..8bbf07e --- /dev/null +++ b/src/main/java/org/ca65/helpers/Cpu.java @@ -0,0 +1,13 @@ +package org.ca65.helpers; + +public enum Cpu { + CPU_6502("6502"), + CPU_65C02("65C02"), + CPU_65C816("65C816"); + + Cpu(String name) { + this.name = name; + } + + public final String name; +} diff --git a/src/main/java/org/ca65/helpers/MnemonicHelper.java b/src/main/java/org/ca65/helpers/MnemonicHelper.java new file mode 100644 index 0000000..7a13377 --- /dev/null +++ b/src/main/java/org/ca65/helpers/MnemonicHelper.java @@ -0,0 +1,148 @@ +package org.ca65.helpers; + +import java.util.Set; + +public class MnemonicHelper { + public static MnemonicInfo[] allMnemnonics = new MnemonicInfo[] { + new MnemonicInfo("adc", "Add Memory to Accumulator with Carry"), + new MnemonicInfo("and", "\"AND\" Memory with Accumulator"), + new MnemonicInfo("asl", "Shift One Bit Left, Memory or Accumulator"), + new MnemonicInfo("bbr0", "Branch on bit 0 reset"), + new MnemonicInfo("bbr1", "Branch on bit 1 reset"), + new MnemonicInfo("bbr2", "Branch on bit 2 reset"), + new MnemonicInfo("bbr3", "Branch on bit 3 reset"), + new MnemonicInfo("bbr4", "Branch on bit 4 reset"), + new MnemonicInfo("bbr5", "Branch on bit 5 reset"), + new MnemonicInfo("bbr6", "Branch on bit 6 reset"), + new MnemonicInfo("bbr7", "Branch on bit 7 reset"), + new MnemonicInfo("bbs0", "Branch on bit 0 set"), + new MnemonicInfo("bbs1", "Branch on bit 1 set"), + new MnemonicInfo("bbs2", "Branch on bit 2 set"), + new MnemonicInfo("bbs3", "Branch on bit 3 set"), + new MnemonicInfo("bbs4", "Branch on bit 4 set"), + new MnemonicInfo("bbs5", "Branch on bit 5 set"), + new MnemonicInfo("bbs6", "Branch on bit 6 set"), + new MnemonicInfo("bbs7", "Branch on bit 7 set"), + new MnemonicInfo("bcc", "Branch on Carry Clear (C=0)"), + new MnemonicInfo("bcs", "Branch on Carry Set (C=1)"), + new MnemonicInfo("beq", "Branch if Equal (Z=1)"), + new MnemonicInfo("bit", "Bit Test"), + new MnemonicInfo("bmi", "Branch if Result Minus (N=1)"), + new MnemonicInfo("bne", "Branch if Not Equal (Z=0)"), + new MnemonicInfo("bpl", "Branch if Result Plus (N=0)"), + new MnemonicInfo("bra", "Branch Always"), + new MnemonicInfo("brk", "Force Break"), + new MnemonicInfo("brl", "Branch Always Long"), + new MnemonicInfo("bvc", "Branch on Overflow Clear (V=0)"), + new MnemonicInfo("bvs", "Branch on Overflow Set (V=1)"), + new MnemonicInfo("clc", "Clear Carry Flag"), + new MnemonicInfo("cld", "Clear Decimal Mode"), + new MnemonicInfo("cli", "Clear Interrupt Disable Bit"), + new MnemonicInfo("clv", "Clear Overflow Flag"), + new MnemonicInfo("cmp", "Compare Memory and Accumulator"), + new MnemonicInfo("cop", "Coprocessor"), + new MnemonicInfo("cpx", "Compare Memory and Index X"), + new MnemonicInfo("cpy", "Compare Memory and Index Y"), + new MnemonicInfo("dec", "Decrement Memory or Accumulator by One"), + new MnemonicInfo("dex", "Decrement Index X by One"), + new MnemonicInfo("dey", "Decrement Index Y by One"), + new MnemonicInfo("eor", "\"Exclusive OR\" Memory with Accumulator"), + new MnemonicInfo("inc", "Increment Memory or Accumulator by One"), + new MnemonicInfo("inx", "Increment Index X by One"), + new MnemonicInfo("iny", "Increment Index Y by One"), + new MnemonicInfo("jml", "Jump Long"), + new MnemonicInfo("jmp", "Jump to New Location"), + new MnemonicInfo("jsl", "Jump Subroutine Long"), + new MnemonicInfo("jsr", "Jump to News Location Saving Return"), + new MnemonicInfo("lda", "Load Accumulator with Memory"), + new MnemonicInfo("ldx", "Load Index X with Memory"), + new MnemonicInfo("ldy", "Load Index Y with Memory"), + new MnemonicInfo("lsr", "Shift One Bit Right (Memory or Accumulator)"), + new MnemonicInfo("mvn", "Block Move Negative"), + new MnemonicInfo("mvp", "Block Move Positive"), + new MnemonicInfo("nop", "No Operation"), + new MnemonicInfo("ora", "\"OR\" Memory with Accumulator"), + new MnemonicInfo("pea", "Push Absolute Address"), + new MnemonicInfo("pei", "Push Indirect Address"), + new MnemonicInfo("per", "Push Program Counter Relative Address"), + new MnemonicInfo("pha", "Push Accumulator on Stack"), + new MnemonicInfo("phb", "Push Data Bank Register on Stack"), + new MnemonicInfo("phd", "Push Direct Register on Stack"), + new MnemonicInfo("phk", "Push Program Bank Register on Stack"), + new MnemonicInfo("php", "Push Processor Status on Stack"), + new MnemonicInfo("phx", "Push Index X on Stack"), + new MnemonicInfo("phy", "Push Index Y on Stack"), + new MnemonicInfo("pla", "Pull Accumulator from Stack"), + new MnemonicInfo("plb", "Pull Data Bank Register from Stack"), + new MnemonicInfo("pld", "Pull Direct Register from Stack"), + new MnemonicInfo("plp", "Pull Processor Status from Stack"), + new MnemonicInfo("plx", "Pull Index X from Stack"), + new MnemonicInfo("ply", "Pull Index Y from Stack"), + new MnemonicInfo("rep", "Reset Status Bits"), + new MnemonicInfo("rmb0", "Reset Memory Bit 0"), + new MnemonicInfo("rmb1", "Reset Memory Bit 1"), + new MnemonicInfo("rmb2", "Reset Memory Bit 2"), + new MnemonicInfo("rmb3", "Reset Memory Bit 3"), + new MnemonicInfo("rmb4", "Reset Memory Bit 4"), + new MnemonicInfo("rmb5", "Reset Memory Bit 5"), + new MnemonicInfo("rmb6", "Reset Memory Bit 6"), + new MnemonicInfo("rmb7", "Reset Memory Bit 7"), + new MnemonicInfo("rol", "Rotate One Bit Left (Memory or Accumulator)"), + new MnemonicInfo("ror", "Rotate One Bit Right"), + new MnemonicInfo("rti", "Return from Interrupt"), + new MnemonicInfo("rtl", "Return from Subroutine Long"), + new MnemonicInfo("rts", "Return from Subroutine"), + new MnemonicInfo("sbc", "Subtract Memory from Accumulator"), + new MnemonicInfo("sep", "Set Processor Status Bit"), + new MnemonicInfo("sec", "Set Carry Flag"), + new MnemonicInfo("sed", "Set Decimal Mode"), + new MnemonicInfo("sei", "Set Interrupt Disable Status"), + new MnemonicInfo("smb0", "Set Memory Bit 0"), + new MnemonicInfo("smb1", "Set Memory Bit 1"), + new MnemonicInfo("smb2", "Set Memory Bit 2"), + new MnemonicInfo("smb3", "Set Memory Bit 3"), + new MnemonicInfo("smb4", "Set Memory Bit 4"), + new MnemonicInfo("smb5", "Set Memory Bit 5"), + new MnemonicInfo("smb6", "Set Memory Bit 6"), + new MnemonicInfo("smb7", "Set Memory Bit 7"), + new MnemonicInfo("sta", "Store Accumulator in Memory"), + new MnemonicInfo("stp", "Stop the Clock"), + new MnemonicInfo("stx", "Store Index X in Memory"), + new MnemonicInfo("sty", "Store Index Y in Memory"), + new MnemonicInfo("stz", "Store Zero in Memory"), + new MnemonicInfo("tax", "Transfer Accumulator in Index X"), + new MnemonicInfo("tay", "Transfer Accumulator to Index Y"), + new MnemonicInfo("tcd", "Transfer C Accumulator to Direct Register"), + new MnemonicInfo("tcs", "Transfer C Accumulator to Stack Pointer"), + new MnemonicInfo("tdc", "Transfer Direct Register to C Accumulator"), + new MnemonicInfo("trb", "Test and Reset Bit"), + new MnemonicInfo("tsb", "Test and Set Bit"), + new MnemonicInfo("tsc", "Transfer Stack Pointer to C Accumulator"), + new MnemonicInfo("tsx", "Transfer Stack Pointer Register to Index X"), + new MnemonicInfo("txa", "Transfer Index X to Accumulator"), + new MnemonicInfo("txs", "Transfer Index X to Stack Pointer Register"), + new MnemonicInfo("txy", "Transfer Index X to Index Y"), + new MnemonicInfo("tya", "Transfer Index Y to Accumulator"), + new MnemonicInfo("tyx", "Transfer Index Y to Index X"), + new MnemonicInfo("wai", "Wait for Interrupt"), + new MnemonicInfo("wdm", "Reserved for future use"), + new MnemonicInfo("xba", "Exchange B and A Accumulator"), + new MnemonicInfo("xce", "Exchange Carry and Emulation Bits"), + }; + + public static Set validMnemnonics65C816 = Set.of("adc", "and", "asl", "bcc", "bcs", "beq", "bit", "bmi", "bne", "bpl", "bra", "brk", "brl", "bvc", "bvs", "clc", "cld", "cli", "clv", "cmp", "cop", "cpx", "cpy", "dec", "dex", "dey", "eor", "inc", "inx", "iny", "jml", "jmp", "jsl", "jsr", "lda", "ldx", "ldy", "lsr", "mvn", "mvp", "nop", "ora", "pea", "pei", "per", "pha", "phb", "phd", "phk", "php", "phx", "phy", "pla", "plb", "pld", "plp", "plx", "ply", "rep", "rol", "ror", "rti", "rtl", "rts", "sbc", "sep", "sec", "sed", "sei", "sta", "stp", "stx", "sty", "stz", "tax", "tay", "tcd", "tcs", "tdc", "trb", "tsb", "tsc", "tsx", "txa", "txs", "txy", "tya", "tyx", "wai", "wdm", "xba", "xce"); + public static Set validMnemnonics65C02 = Set.of("adc", "and", "asl", "bbr0", "bbr1", "bbr2", "bbr3", "bbr4", "bbr5", "bbr6", "bbr7", "bbs0", "bbs1", "bbs2", "bbs3", "bbs4", "bbs5", "bbs6", "bbs7", "bcc", "bcs", "beq", "bit", "bmi", "bne", "bpl", "bra", "brk", "bvc", "bvs", "clc", "cld", "cli", "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey", "eor", "inc", "inx", "iny", "jmp", "jsr", "lda", "ldx", "ldy", "lsr", "nop", "ora", "pha", "php", "phx", "phy", "pla", "plp", "plx", "ply", "rmb0", "rmb1", "rmb2", "rmb3", "rmb4", "rmb5", "rmb6", "rmb7", "rol", "ror", "rti", "rts", "sbc", "sec", "sed", "sei", "smb0", "smb1", "smb2", "smb3", "smb4", "smb5", "smb6", "smb7", "sta", "stp", "stx", "sty", "stz", "tax", "tay", "trb", "tsb", "tsx", "txa", "txs", "tya", "wai"); + public static Set validMnemnonics6502 = Set.of("adc", "and", "asl", "bcc", "bcs", "beq", "bit", "bmi", "bne", "bpl", "brk", "bvc", "bvs", "clc", "cld", "cli", "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey", "eor", "inc", "inx", "iny", "jmp", "jsr", "lda", "ldx", "ldy", "lsr", "nop", "ora", "pha", "php", "pla", "plp", "ror", "rti", "rts", "sbc", "sec", "sed", "sei", "sta", "stx", "sty", "tax", "tay", "tsx", "txa", "txs", "tya"); + + public static Set getMnemonicsForCpu(Cpu cpu) { + switch (cpu) { + case CPU_6502: + return validMnemnonics6502; + case CPU_65C02: + return validMnemnonics65C02; + case CPU_65C816: + return validMnemnonics65C816; + } + throw new UnsupportedOperationException("Unknown CPU " + cpu); + } +} diff --git a/src/main/java/org/ca65/helpers/MnemonicInfo.java b/src/main/java/org/ca65/helpers/MnemonicInfo.java new file mode 100644 index 0000000..028d63e --- /dev/null +++ b/src/main/java/org/ca65/helpers/MnemonicInfo.java @@ -0,0 +1,11 @@ +package org.ca65.helpers; + +public class MnemonicInfo { + public String mnemnonic; + public String description; + + public MnemonicInfo(String mnemonic, String description) { + this.mnemnonic = mnemonic; + this.description = description; + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index fb66cf5..a808ae1 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -41,8 +41,10 @@ - + + + org.ca65.action.ConvertNumberToHexadecimalIntentionAction diff --git a/src/main/resources/messages/Asm6502Bundle.properties b/src/main/resources/messages/Asm6502Bundle.properties index eda165a..34d216c 100644 --- a/src/main/resources/messages/Asm6502Bundle.properties +++ b/src/main/resources/messages/Asm6502Bundle.properties @@ -8,3 +8,6 @@ INTN.convert.to.dec=Convert ''{0}'' to decimal INTN.NAME.convert.to.bin=Convert to binary INTN.convert.to.bin=Convert ''{0}'' to binary + +INTN.NAME.change.cpu=Change project CPU target +INTN.change.cpu=Target the {0} CPU for this project diff --git a/templates/Generic 6502 Project/.idea/workspace.xml b/templates/Generic 6502 Project/.idea/workspace.xml deleted file mode 100644 index 9d35f60..0000000 --- a/templates/Generic 6502 Project/.idea/workspace.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/templates/Generic 6502 Project/root0/Generic 6502 Project.iml b/templates/Generic 6502 Project/root0/Generic 6502 Project.iml new file mode 100644 index 0000000..01747b6 --- /dev/null +++ b/templates/Generic 6502 Project/root0/Generic 6502 Project.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/templates/Generic 6502 Project/Makefile b/templates/Generic 6502 Project/root0/Makefile similarity index 100% rename from templates/Generic 6502 Project/Makefile rename to templates/Generic 6502 Project/root0/Makefile diff --git a/templates/Generic 6502 Project/hello.cfg b/templates/Generic 6502 Project/root0/hello.cfg similarity index 100% rename from templates/Generic 6502 Project/hello.cfg rename to templates/Generic 6502 Project/root0/hello.cfg diff --git a/templates/Generic 6502 Project/hello.s b/templates/Generic 6502 Project/root0/hello.s similarity index 99% rename from templates/Generic 6502 Project/hello.s rename to templates/Generic 6502 Project/root0/hello.s index ba9db92..8497c76 100644 --- a/templates/Generic 6502 Project/hello.s +++ b/templates/Generic 6502 Project/root0/hello.s @@ -14,3 +14,4 @@ reset: ldx #$41 ; Letter A lda #$0a ; Newline jsr sim_putchar jmp sim_exit +