diff --git a/src/dk/camelot64/kickc/asm/AsmAddressingMode.java b/src/dk/camelot64/kickc/asm/AsmAddressingMode.java new file mode 100644 index 000000000..e8bb8af4c --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmAddressingMode.java @@ -0,0 +1,47 @@ +package dk.camelot64.kickc.asm; + +/** 6502 Assembler Instruction Addressing Modes. */ +public enum AsmAddressingMode { + NON("", "%i", 1), + IMM("#imm", "%i #%p", 2), + ZP("zp", "%i %p", 2), + ZPX("zp,x", "%i %p,x", 2), + ZPY("zp,y", "%i %p,y", 2), + ABS("abs", "%i %p", 3), + ABX("abs,x", "%i %p,x", 3), + ABY("abs,y", "%i %p,y", 4), + IZX("(zp,x)", "%i (%p,x)", 2), + IZY("(zp),y", "%i (%p),y", 2), + REL("rel", "%i %p", 2), + IND("(ind)", "%i (%p)", 3); + + + private String name; + + private String template; + + private int bytes; + + AsmAddressingMode(String name, String template, int bytes) { + this.bytes = bytes; + this.template = template; + this.name = name; + } + + public int getBytes() { + return bytes; + } + + public String getName() { + return name; + } + + public String getAsm(String mnemnonic, String parameter) { + String replaced = template.replace("%i", mnemnonic); + if(parameter!=null) { + replaced = replaced.replace("%p", parameter); + } + return replaced; + } + +} diff --git a/src/dk/camelot64/kickc/asm/AsmComment.java b/src/dk/camelot64/kickc/asm/AsmComment.java new file mode 100644 index 000000000..6f00c415e --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmComment.java @@ -0,0 +1,35 @@ +package dk.camelot64.kickc.asm; + +/** An assember comment */ +public class AsmComment implements AsmLine { + private String comment; + + public AsmComment(String comment) { + this.comment = comment; + } + + @Override + public int getLineBytes() { + return 0; + } + + @Override + public double getLineCycles() { + return 0; + } + + @Override + public int getInvocationCountEstimate() { + return 0; + } + + @Override + public double getEstimatedTotalCycles() { + return 0; + } + + @Override + public String getAsm() { + return "// "+comment; + } +} diff --git a/src/dk/camelot64/kickc/icl/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java similarity index 59% rename from src/dk/camelot64/kickc/icl/AsmFragment.java rename to src/dk/camelot64/kickc/asm/AsmFragment.java index 3594f52eb..90c321b35 100644 --- a/src/dk/camelot64/kickc/icl/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -1,9 +1,13 @@ -package dk.camelot64.kickc.icl; +package dk.camelot64.kickc.asm; + +import dk.camelot64.kickc.asm.parser.Asm6502BaseVisitor; +import dk.camelot64.kickc.asm.parser.Asm6502Lexer; +import dk.camelot64.kickc.asm.parser.Asm6502Parser; +import dk.camelot64.kickc.icl.*; +import org.antlr.v4.runtime.*; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -26,7 +30,7 @@ public class AsmFragment { private Map bindings; /** - * The string signature/name of the asm fragment. + * The string signature/name of the fragment fragment. */ private String signature; @@ -106,8 +110,8 @@ public class AsmFragment { case ">=": case "=>": return "_ge_"; - default: - return op; + default: + return op; } } @@ -197,7 +201,7 @@ public class AsmFragment { * @param name The name of the bound value in the fragment * @return The bound value to use in the generated ASM code */ - public String getValue(String name) { + public String getBoundValue(String name) { Value boundValue = getBinding(name); String bound; if (boundValue instanceof Variable) { @@ -232,27 +236,30 @@ public class AsmFragment { public void generateAsm(AsmSequence asm) { String signature = this.getSignature(); ClassLoader classLoader = this.getClass().getClassLoader(); - URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/icl/asm/" + signature + ".asm"); + final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm"); if (fragmentResource == null) { System.out.println("Fragment not found " + fragmentResource); asm.addAsm(" // Fragment not found: " + signature); return; } - Pattern bindPattern = Pattern.compile(".*\\{([^}]*)}.*"); + try { InputStream fragmentStream = fragmentResource.openStream(); - BufferedReader fragmentReader = new BufferedReader(new InputStreamReader(fragmentStream)); - String line; - while ((line = fragmentReader.readLine()) != null) { - Matcher matcher = bindPattern.matcher(line); - if (matcher.matches()) { - String name = matcher.group(1); - String bound = this.getValue(name); - line = line.replaceFirst("\\{[^}]*}", bound); + Asm6502Lexer lexer = new Asm6502Lexer(new ANTLRInputStream(fragmentStream)); + Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer)); + parser.addErrorListener(new BaseErrorListener() { + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { + throw new RuntimeException("Error parsing fragment file "+fragmentResource+"\n - Line: "+line+"\n - Message: "+msg); } - asm.addAsm(" " + line); + }); + parser.setBuildParseTree(true); + Asm6502Parser.FileContext file = parser.file(); + AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(fragmentResource); + asmSequenceGenerator.generate(file); + for (AsmLine asmLine : asmSequenceGenerator.program.getLines()) { + asm.addAsm(" "+asmLine.getAsm()); } - fragmentReader.close(); fragmentStream.close(); } catch (IOException e) { throw new RuntimeException("Error reading code fragment " + fragmentResource); @@ -260,5 +267,119 @@ public class AsmFragment { } + private class AsmSequenceGenerator extends Asm6502BaseVisitor { + + private URL fragmentResource; + private AsmProgram program; + + public AsmSequenceGenerator(URL fragmentResource, AsmProgram program) { + this.fragmentResource = fragmentResource; + this.program = program; + } + + public AsmSequenceGenerator(URL fragmentResource) { + this.fragmentResource = fragmentResource; + this.program = new AsmProgram(); + } + + public AsmProgram getProgram() { + return program; + } + + public void generate(Asm6502Parser.FileContext context) { + this.visit(context); + } + + @Override + public Object visitLabel(Asm6502Parser.LabelContext ctx) { + program.addLine(new AsmLabel(ctx.getChild(0).getText())); + return null; + } + + @Override + public Object visitComment(Asm6502Parser.CommentContext ctx) { + program.addLine(new AsmComment(ctx.getChild(1).getText())); + return null; + } + + + @Override + public Object visitInstruction(Asm6502Parser.InstructionContext ctx) { + Asm6502Parser.ParamModeContext paramModeCtx = ctx.paramMode(); + AsmInstruction instruction; + if(paramModeCtx==null) { + AsmInstructionType type = AsmInstuctionSet.getInstructionType(ctx.MNEMONIC().getText(), AsmAddressingMode.NON); + instruction = new AsmInstruction(type, null, 1); + } else { + instruction = (AsmInstruction) this.visit(paramModeCtx); + } + if(instruction!=null) { + program.addLine(instruction); + } else { + throw new RuntimeException("Error parsing ASM fragment line in "+fragmentResource.toString()+"\n - Line: "+ctx.getText()); + } + return null; + } + + @Override + public Object visitModeAbs(Asm6502Parser.ModeAbsContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABS); + } + + @Override + public Object visitModeImm(Asm6502Parser.ModeImmContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IMM); + } + + @Override + public Object visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABX); + } + + @Override + public Object visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.ABY); + } + + @Override + public Object visitModeIndY(Asm6502Parser.ModeIndYContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IZY); + } + + @Override + public Object visitModeIndX(Asm6502Parser.ModeIndXContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IZX); + } + + @Override + public Object visitModeInd(Asm6502Parser.ModeIndContext ctx) { + return createAsmInstruction(ctx, ctx.param(), AsmAddressingMode.IND); + } + + private AsmInstruction createAsmInstruction(Asm6502Parser.ParamModeContext ctx, Asm6502Parser.ParamContext paramCtx, AsmAddressingMode addressingMode) { + Asm6502Parser.InstructionContext instructionCtx = (Asm6502Parser.InstructionContext) ctx.getParent(); + String mnemonic = instructionCtx.MNEMONIC().getSymbol().getText(); + String parameter = (String) this.visit(paramCtx); + AsmInstructionType type = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode); + return new AsmInstruction(type, parameter, 1); + } + + @Override + public Object visitParamInt(Asm6502Parser.ParamIntContext ctx) { + return NumberParser.parseLiteral(ctx.NUMINT().getText()).toString(); + } + + @Override + public Object visitParamLabel(Asm6502Parser.ParamLabelContext ctx) { + return ctx.NAME().getSymbol().getText(); + } + + @Override + public Object visitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { + String replaceName = ctx.NAME().getSymbol().getText(); + return AsmFragment.this.getBoundValue(replaceName); + } + } + } diff --git a/src/dk/camelot64/kickc/asm/AsmInstruction.java b/src/dk/camelot64/kickc/asm/AsmInstruction.java new file mode 100644 index 000000000..130c68907 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmInstruction.java @@ -0,0 +1,45 @@ +package dk.camelot64.kickc.asm; + +/** An assembler instruction */ +public class AsmInstruction implements AsmLine { + + private AsmInstructionType type; + + private String parameter; + + private int invocationCountEstimate; + + public AsmInstruction(AsmInstructionType type, String parameter, int invocationCountEstimate) { + this.type = type; + this.parameter = parameter; + this.invocationCountEstimate = invocationCountEstimate; + } + + @Override + public int getLineBytes() { + return type.getBytes(); + } + + @Override + public double getLineCycles() { + return type.getCycles(); + } + + @Override + public int getInvocationCountEstimate() { + return invocationCountEstimate; + } + + @Override + public double getEstimatedTotalCycles() { + return getInvocationCountEstimate()*getLineCycles(); + } + + + @Override + public String getAsm() { + return type.getAsm(parameter); + } + + +} diff --git a/src/dk/camelot64/kickc/asm/AsmInstructionType.java b/src/dk/camelot64/kickc/asm/AsmInstructionType.java new file mode 100644 index 000000000..71ebd0d46 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmInstructionType.java @@ -0,0 +1,41 @@ +package dk.camelot64.kickc.asm; + +/** The instructions of the 6502 assembler instruction set */ +public class AsmInstructionType { + + private int opcode; + + private String mnemnonic; + + private AsmAddressingMode addressingMode; + + private double cycles; + + public AsmInstructionType(int opcode, String mnemnonic, AsmAddressingMode addressingMode, double cycles) { + this.opcode = opcode; + this.mnemnonic = mnemnonic; + this.addressingMode = addressingMode; + this.cycles = cycles; + } + + public String getMnemnonic() { + return mnemnonic; + } + + public AsmAddressingMode getAddressingMode() { + return addressingMode; + } + + public double getCycles() { + return cycles; + } + + public int getBytes() { + return addressingMode.getBytes(); + } + + public String getAsm(String parameter) { + return addressingMode.getAsm(mnemnonic, parameter); + } + +} diff --git a/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java b/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java new file mode 100644 index 000000000..4ad232b2c --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java @@ -0,0 +1,312 @@ +package dk.camelot64.kickc.asm; + +import java.util.ArrayList; +import java.util.List; + +/** + * The set of all 6502 assembler instructions + */ +public class AsmInstuctionSet { + + private static AsmInstuctionSet set = new AsmInstuctionSet(); + + public static AsmInstructionType getInstructionType(String mnemonic, AsmAddressingMode mode) { + AsmInstructionType type = set.getType(mnemonic, mode); + if(type==null && AsmAddressingMode.ABS.equals(mode)) { + type = set.getType(mnemonic, AsmAddressingMode.REL); + } + return type; + } + + + + private List instructions; + + private void add(int opcode, String mnemonic, AsmAddressingMode addressingmMode, double cycles) { + instructions.add(new AsmInstructionType(opcode, mnemonic.toLowerCase(), addressingmMode, cycles)); + } + + public AsmInstuctionSet() { + this.instructions = new ArrayList<>(); + AsmAddressingMode non = AsmAddressingMode.NON; + AsmAddressingMode zp = AsmAddressingMode.ZP; + AsmAddressingMode zpx = AsmAddressingMode.ZPX; + AsmAddressingMode zpy = AsmAddressingMode.ZPY; + AsmAddressingMode imm = AsmAddressingMode.IMM; + AsmAddressingMode abs = AsmAddressingMode.ABS; + AsmAddressingMode abx = AsmAddressingMode.ABX; + AsmAddressingMode aby = AsmAddressingMode.ABY; + AsmAddressingMode izx = AsmAddressingMode.IZX; + AsmAddressingMode izy = AsmAddressingMode.IZY; + AsmAddressingMode rel = AsmAddressingMode.REL; + AsmAddressingMode ind = AsmAddressingMode.IND; + add(0x00, "BRK", non, 7.0); + add(0x01, "ORA", izx, 6.0); + add(0x01, "ORA", izx, 6.0); + add(0x02, "KIL", non, 0.0); + add(0x03, "SLO", izx, 8.0); + add(0x04, "NOP", zp, 3.0); + add(0x05, "ORA", zp, 3.0); + add(0x06, "ASL", zp, 5.0); + add(0x07, "SLO", zp, 5.0); + add(0x08, "PHP", non, 3.0); + add(0x09, "ORA", imm, 2.0); + add(0x0a, "ASL", non, 2.0); + add(0x0b, "ANC", imm, 2.0); + add(0x0c, "NOP", abs, 4.0); + add(0x0d, "ORA", abs, 4.0); + add(0x0e, "ASL", abs, 6.0); + add(0x0f, "SLO", abs, 6.0); + add(0x10, "BPL", rel, 2.5); + add(0x11, "ORA", izy, 5.5); + add(0x12, "KIL", non, 0.0); + add(0x13, "SLO", izy, 8.0); + add(0x14, "NOP", zpx, 4.0); + add(0x15, "ORA", zpx, 4.0); + add(0x16, "ASL", zpx, 6.0); + add(0x17, "SLO", zpx, 6.0); + add(0x18, "CLC", non, 2.0); + add(0x19, "ORA", aby, 4.5); + add(0x1a, "NOP", non, 2.0); + add(0x1b, "SLO", aby, 7.0); + add(0x1c, "NOP", abx, 4.5); + add(0x1d, "ORA", abx, 4.5); + add(0x1e, "ASL", abx, 7.0); + add(0x1f, "SLO", abx, 7.0); + add(0x20, "JSR", abs, 6.0); + add(0x21, "AND", izx, 6.0); + add(0x22, "KIL", non, 0.0); + add(0x23, "RLA", izx, 8.0); + add(0x24, "BIT", zp, 3.0); + add(0x25, "AND", zp, 3.0); + add(0x26, "ROL", zp, 5.0); + add(0x27, "RLA", zp, 5.0); + add(0x28, "PLP", non, 4.0); + add(0x29, "AND", imm, 2.0); + add(0x2a, "ROL", non, 2.0); + add(0x2b, "ANC", imm, 2.0); + add(0x2c, "BIT", abs, 4.0); + add(0x2d, "AND", abs, 4.0); + add(0x2e, "ROL", abs, 6.0); + add(0x2f, "RLA", abs, 6.0); + add(0x30, "BMI", rel, 2.5); + add(0x31, "AND", izy, 5.5); + add(0x32, "KIL", non, 0.0); + add(0x33, "RLA", izy, 8.0); + add(0x34, "NOP", zpx, 4.0); + add(0x35, "AND", zpx, 4.0); + add(0x36, "ROL", zpx, 6.0); + add(0x37, "RLA", zpx, 6.0); + add(0x38, "SEC", non, 2.0); + add(0x39, "AND", aby, 4.5); + add(0x3a, "NOP", non, 2.0); + add(0x3b, "RLA", aby, 7.0); + add(0x3c, "NOP", abx, 4.5); + add(0x3d, "AND", abx, 4.5); + add(0x3e, "ROL", abx, 7.0); + add(0x3f, "RLA", abx, 7.0); + add(0x40, "RTI", non, 6.0); + add(0x41, "EOR", izx, 6.0); + add(0x42, "KIL", non, 0.0); + add(0x43, "SRE", izx, 8.0); + add(0x44, "NOP", zp, 3.0); + add(0x45, "EOR", zp, 3.0); + add(0x46, "LSR", zp, 5.0); + add(0x47, "SRE", zp, 5.0); + add(0x48, "PHA", non, 3.0); + add(0x49, "EOR", imm, 2.0); + add(0x4a, "LSR", non, 2.0); + add(0x4b, "ALR", imm, 2.0); + add(0x4c, "JMP", abs, 3.0); + add(0x4d, "EOR", abs, 4.0); + add(0x4e, "LSR", abs, 6.0); + add(0x4f, "SRE", abs, 6.0); + add(0x50, "BVC", rel, 2.5); + add(0x51, "EOR", izy, 5.5); + add(0x52, "KIL", non, 0.0); + add(0x53, "SRE", izy, 8.0); + add(0x54, "NOP", zpx, 4.0); + add(0x55, "EOR", zpx, 4.0); + add(0x56, "LSR", zpx, 6.0); + add(0x57, "SRE", zpx, 6.0); + add(0x58, "CLI", non, 2.0); + add(0x59, "EOR", aby, 4.5); + add(0x5a, "NOP", non, 2.0); + add(0x5b, "SRE", aby, 7.0); + add(0x5c, "NOP", abx, 4.5); + add(0x5d, "EOR", abx, 4.5); + add(0x5e, "LSR", abx, 7.0); + add(0x5f, "SRE", abx, 7.0); + add(0x60, "RTS", non, 6.0); + add(0x61, "ADC", izx, 6.0); + add(0x62, "KIL", non, 0.0); + add(0x63, "RRA", izx, 8.0); + add(0x64, "NOP", zp, 3.0); + add(0x65, "ADC", zp, 3.0); + add(0x66, "ROR", zp, 5.0); + add(0x67, "RRA", zp, 5.0); + add(0x68, "PLA", non, 4.0); + add(0x69, "ADC", imm, 2.0); + add(0x6a, "ROR", non, 2.0); + add(0x6b, "ARR", imm, 2.0); + add(0x6c, "JMP", ind, 5.0); + add(0x6d, "ADC", abs, 4.0); + add(0x6e, "ROR", abs, 6.0); + add(0x6f, "RRA", abs, 6.0); + add(0x70, "BVS", rel, 2.5); + add(0x71, "ADC", izy, 5.5); + add(0x72, "KIL", non, 0.0); + add(0x73, "RRA", izy, 8.0); + add(0x74, "NOP", zpx, 4.0); + add(0x75, "ADC", zpx, 4.0); + add(0x76, "ROR", zpx, 6.0); + add(0x77, "RRA", zpx, 6.0); + add(0x78, "SEI", non, 2.0); + add(0x79, "ADC", aby, 4.5); + add(0x7a, "NOP", non, 2.0); + add(0x7b, "RRA", aby, 7.0); + add(0x7c, "NOP", abx, 4.5); + add(0x7d, "ADC", abx, 4.5); + add(0x7e, "ROR", abx, 7.0); + add(0x7f, "RRA", abx, 7.0); + add(0x80, "NOP", imm, 2.0); + add(0x81, "STA", izx, 6.0); + add(0x82, "NOP", imm, 2.0); + add(0x83, "SAX", izx, 6.0); + add(0x84, "STY", zp, 3.0); + add(0x85, "STA", zp, 3.0); + add(0x86, "STX", zp, 3.0); + add(0x87, "SAX", zp, 3.0); + add(0x88, "DEY", non, 2.0); + add(0x89, "NOP", imm, 2.0); + add(0x8a, "TXA", non, 2.0); + add(0x8b, "XAA", imm, 2.0); + add(0x8c, "STY", abs, 4.0); + add(0x8d, "STA", abs, 4.0); + add(0x8e, "STX", abs, 4.0); + add(0x8f, "SAX", abs, 4.0); + add(0x90, "BCC", rel, 2.5); + add(0x91, "STA", izy, 6.0); + add(0x92, "KIL", non, 0.0); + add(0x93, "AHX", izy, 6.0); + add(0x94, "STY", zpx, 4.0); + add(0x95, "STA", zpx, 4.0); + add(0x96, "STX", zpy, 4.0); + add(0x97, "SAX", zpy, 4.0); + add(0x98, "TYA", non, 2.0); + add(0x99, "STA", aby, 5.0); + add(0x9a, "TXS", non, 2.0); + add(0x9b, "TAS", aby, 5.0); + add(0x9c, "SHY", abx, 5.0); + add(0x9d, "STA", abx, 5.0); + add(0x9e, "SHX", aby, 5.0); + add(0x9f, "AHX", aby, 5.0); + add(0xa0, "LDY", imm, 2.0); + add(0xa1, "LDA", izx, 6.0); + add(0xa2, "LDX", imm, 2.0); + add(0xa3, "LAX", izx, 6.0); + add(0xa4, "LDY", zp, 3.0); + add(0xa5, "LDA", zp, 3.0); + add(0xa6, "LDX", zp, 3.0); + add(0xa7, "LAX", zp, 3.0); + add(0xa8, "TAY", non, 2.0); + add(0xa9, "LDA", imm, 2.0); + add(0xaa, "TAX", non, 2.0); + add(0xab, "LAX", imm, 2.0); + add(0xac, "LDY", abs, 4.0); + add(0xad, "LDA", abs, 4.0); + add(0xae, "LDX", abs, 4.0); + add(0xaf, "LAX", abs, 4.0); + add(0xb0, "BCS", rel, 2.5); + add(0xb1, "LDA", izy, 5.5); + add(0xb2, "KIL", non, 0.0); + add(0xb3, "LAX", izy, 5.5); + add(0xb4, "LDY", zpx, 4.0); + add(0xb5, "LDA", zpx, 4.0); + add(0xb6, "LDX", zpy, 4.0); + add(0xb7, "LAX", zpy, 4.0); + add(0xb8, "CLV", non, 2.0); + add(0xb9, "LDA", aby, 4.5); + add(0xba, "TSX", non, 2.0); + add(0xbb, "LAS", aby, 4.5); + add(0xbc, "LDY", abx, 4.5); + add(0xbd, "LDA", abx, 4.5); + add(0xbe, "LDX", aby, 4.5); + add(0xbf, "LAX", aby, 4.5); + add(0xc0, "CPY", imm, 2.0); + add(0xc1, "CMP", izx, 6.0); + add(0xc2, "NOP", imm, 2.0); + add(0xc3, "DCP", izx, 8.0); + add(0xc4, "CPY", zp, 3.0); + add(0xc5, "CMP", zp, 3.0); + add(0xc6, "DEC", zp, 5.0); + add(0xc7, "DCP", zp, 5.0); + add(0xc8, "INY", non, 2.0); + add(0xc9, "CMP", imm, 2.0); + add(0xca, "DEX", non, 2.0); + add(0xcb, "AXS", imm, 2.0); + add(0xcc, "CPY", abs, 4.0); + add(0xcd, "CMP", abs, 4.0); + add(0xce, "DEC", abs, 6.0); + add(0xcf, "DCP", abs, 6.0); + add(0xd0, "BNE", rel, 2.5); + add(0xd1, "CMP", izy, 5.5); + add(0xd2, "KIL", non, 0.0); + add(0xd3, "DCP", izy, 8.0); + add(0xd4, "NOP", zpx, 4.0); + add(0xd5, "CMP", zpx, 4.0); + add(0xd6, "DEC", zpx, 6.0); + add(0xd7, "DCP", zpx, 6.0); + add(0xd8, "CLD", non, 2.0); + add(0xd9, "CMP", aby, 4.5); + add(0xda, "NOP", non, 2.0); + add(0xdb, "DCP", aby, 7.0); + add(0xdc, "NOP", abx, 4.5); + add(0xdd, "CMP", abx, 4.5); + add(0xde, "DEC", abx, 7.0); + add(0xef, "CPX", imm, 2.0); + add(0xe0, "SBC", izx, 6.0); + add(0xe1, "NOP", imm, 2.0); + add(0xe2, "ISC", izx, 8.0); + add(0xe3, "CPX", zp, 3.0); + add(0xe4, "SBC", zp, 3.0); + add(0xe5, "INC", zp, 5.0); + add(0xe6, "ISC", zp, 5.0); + add(0xe7, "INX", non, 2.0); + add(0xe8, "SBC", imm, 2.0); + add(0xe9, "NOP", non, 2.0); + add(0xea, "SBC", imm, 2.0); + add(0xeb, "CPX", abs, 4.0); + add(0xec, "SBC", abs, 4.0); + add(0xed, "INC", abs, 6.0); + add(0xee, "ISC", abs, 6.0); + add(0xef, "DCP", abx, 7.0); + add(0xf0, "BEQ", rel, 2.5); + add(0xf1, "SBC", izy, 5.5); + add(0xf2, "KIL", non, 0.0); + add(0xf3, "ISC", izy, 8.0); + add(0xf4, "NOP", zpx, 4.0); + add(0xf5, "SBC", zpx, 4.0); + add(0xf6, "INC", zpx, 6.0); + add(0xf7, "ISC", zpx, 6.0); + add(0xf8, "SED", non, 2.0); + add(0xf9, "SBC", aby, 4.5); + add(0xfa, "NOP", non, 2.0); + add(0xfb, "ISC", aby, 7.0); + add(0xfc, "NOP", abx, 4.5); + add(0xfd, "SBC", abx, 4.5); + add(0xfe, "INC", abx, 7.0); + add(0xff, "ISC", abx, 7.0); + + } + + public AsmInstructionType getType(String mnemonic, AsmAddressingMode addressingMode) { + for (AsmInstructionType candidate : instructions) { + if(candidate.getMnemnonic().equals(mnemonic.toLowerCase()) && candidate.getAddressingMode().equals(addressingMode)) { + return candidate; + } + } + return null; + } + +} diff --git a/src/dk/camelot64/kickc/asm/AsmLabel.java b/src/dk/camelot64/kickc/asm/AsmLabel.java new file mode 100644 index 000000000..622a4803f --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmLabel.java @@ -0,0 +1,36 @@ +package dk.camelot64.kickc.asm; + +/** A label / jump target */ +public class AsmLabel implements AsmLine { + + private String label; + + public AsmLabel(String label) { + this.label = label; + } + + @Override + public int getLineBytes() { + return 0; + } + + @Override + public double getLineCycles() { + return 0; + } + + @Override + public int getInvocationCountEstimate() { + return 0; + } + + @Override + public double getEstimatedTotalCycles() { + return 0; + } + + @Override + public String getAsm() { + return ":"+label; + } +} diff --git a/src/dk/camelot64/kickc/asm/AsmLine.java b/src/dk/camelot64/kickc/asm/AsmLine.java new file mode 100644 index 000000000..1fcfb2c6b --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmLine.java @@ -0,0 +1,16 @@ +package dk.camelot64.kickc.asm; + +/** A line of 6502 assembler code */ +public interface AsmLine { + + public int getLineBytes(); + + public double getLineCycles(); + + public int getInvocationCountEstimate(); + + public double getEstimatedTotalCycles(); + + public String getAsm(); + +} diff --git a/src/dk/camelot64/kickc/asm/AsmProgram.java b/src/dk/camelot64/kickc/asm/AsmProgram.java new file mode 100644 index 000000000..1c7d850e7 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/AsmProgram.java @@ -0,0 +1,22 @@ +package dk.camelot64.kickc.asm; + +import java.util.ArrayList; +import java.util.List; + +/** A 6502 assembler program */ +public class AsmProgram { + + private List lines; + + public AsmProgram() { + this.lines = new ArrayList<>(); + } + + public List getLines() { + return lines; + } + + public void addLine(AsmLine line) { + lines.add(line); + } +} diff --git a/src/dk/camelot64/kickc/icl/AsmSequence.java b/src/dk/camelot64/kickc/asm/AsmSequence.java similarity index 96% rename from src/dk/camelot64/kickc/icl/AsmSequence.java rename to src/dk/camelot64/kickc/asm/AsmSequence.java index 9ba99df04..cabd2c085 100644 --- a/src/dk/camelot64/kickc/icl/AsmSequence.java +++ b/src/dk/camelot64/kickc/asm/AsmSequence.java @@ -1,4 +1,4 @@ -package dk.camelot64.kickc.icl; +package dk.camelot64.kickc.asm; import java.util.ArrayList; import java.util.List; diff --git a/src/dk/camelot64/kickc/asm/fragment/xby=coby1.asm b/src/dk/camelot64/kickc/asm/fragment/xby=coby1.asm new file mode 100644 index 000000000..95c8c2fa8 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/xby=coby1.asm @@ -0,0 +1 @@ +ldx #{coby1} diff --git a/src/dk/camelot64/kickc/asm/fragment/xby=xby_minus_1.asm b/src/dk/camelot64/kickc/asm/fragment/xby=xby_minus_1.asm new file mode 100644 index 000000000..125cf09a3 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/xby=xby_minus_1.asm @@ -0,0 +1 @@ +dex diff --git a/src/dk/camelot64/kickc/asm/fragment/xby_gt_0_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/xby_gt_0_then_la1.asm new file mode 100644 index 000000000..55b9cb6c2 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/xby_gt_0_then_la1.asm @@ -0,0 +1,2 @@ +cpx #0 +bne {la1} diff --git a/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_gt_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_gt_coby1.asm new file mode 100644 index 000000000..2d5f4a5c2 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_gt_coby1.asm @@ -0,0 +1,11 @@ + LDA {zpby1} + CMP #{coby1} + BEQ !f+ + BCS !t+ +!f: + LDA #0 + JMP !d+ +!t: + LDA #$ff +!d: + STA {zpbo1} diff --git a/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_le_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_le_coby1.asm similarity index 82% rename from src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_le_coby1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_le_coby1.asm index d710663d5..ecccc4e19 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_le_coby1.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_le_coby1.asm @@ -5,4 +5,4 @@ beq !t+ !f: lda #0 jmp !d+ !t: lda #$ff -!d: sta {zpbo1} \ No newline at end of file +!d: sta {zpbo1 diff --git a/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_lt_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_lt_coby1.asm similarity index 80% rename from src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_lt_coby1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_lt_coby1.asm index 825f8b359..924b85821 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_lt_coby1.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpbo1=zpby1_lt_coby1.asm @@ -4,4 +4,4 @@ bcc !t+ !f: lda #0 jmp !d+ !t: lda #$ff -!d: sta {zpbo1} \ No newline at end of file +!d: sta {zpbo1} diff --git a/src/dk/camelot64/kickc/icl/asm/zpbo1_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpbo1_then_la1.asm similarity index 100% rename from src/dk/camelot64/kickc/icl/asm/zpbo1_then_la1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpbo1_then_la1.asm diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=coby1.asm similarity index 52% rename from src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1=coby1.asm index 74a2a50a8..68252d812 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpby1=coby1.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=coby1.asm @@ -1,2 +1,2 @@ lda #{coby1} -sta {zpby1} \ No newline at end of file +sta {zpby1} diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2.asm similarity index 50% rename from src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2.asm index f52963699..c49b5d65b 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2.asm @@ -1,2 +1,2 @@ lda {zpby2} -sta {zpby1} \ No newline at end of file +sta {zpby1} diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_minus_1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_minus_1.asm new file mode 100644 index 000000000..9e8babc6b --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_minus_1.asm @@ -0,0 +1,4 @@ +lda {zpby2} +sec +sbc #1 +sta {zpby1} diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_minus_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_minus_coby1.asm similarity index 70% rename from src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_minus_coby1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_minus_coby1.asm index a1cc2cef9..b22d21688 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_minus_coby1.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_minus_coby1.asm @@ -1,4 +1,4 @@ lda {zpby2} sec sbc #{coby1} -sta {zpby1} \ No newline at end of file +sta {zpby1} diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_1.asm new file mode 100644 index 000000000..44b347210 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_1.asm @@ -0,0 +1,4 @@ +lda {zpby1} +clc +adc #1 +sta {zpby2} diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_plus_coby1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_coby1.asm similarity index 100% rename from src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_plus_coby1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_coby1.asm diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_plus_zpby3.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_zpby3.asm similarity index 70% rename from src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_plus_zpby3.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_zpby3.asm index 3a5edaaa0..a61eea457 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpby1=zpby2_plus_zpby3.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1=zpby2_plus_zpby3.asm @@ -1,4 +1,4 @@ lda {zpby2} clc adc {zpby3} -sta {zpby1} \ No newline at end of file +sta {zpby1} diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1_gt_0_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1_gt_0_then_la1.asm similarity index 100% rename from src/dk/camelot64/kickc/icl/asm/zpby1_gt_0_then_la1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1_gt_0_then_la1.asm diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1_gt_coby1_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1_gt_coby1_then_la1.asm similarity index 93% rename from src/dk/camelot64/kickc/icl/asm/zpby1_gt_coby1_then_la1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1_gt_coby1_then_la1.asm index 7da7bd205..ecc88c62f 100644 --- a/src/dk/camelot64/kickc/icl/asm/zpby1_gt_coby1_then_la1.asm +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1_gt_coby1_then_la1.asm @@ -2,4 +2,4 @@ lda {zpby1} cmp #{coby1} beq !+ bcs {la1} -!: \ No newline at end of file +!: diff --git a/src/dk/camelot64/kickc/icl/asm/zpby1_le_coby1_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1_le_coby1_then_la1.asm similarity index 100% rename from src/dk/camelot64/kickc/icl/asm/zpby1_le_coby1_then_la1.asm rename to src/dk/camelot64/kickc/asm/fragment/zpby1_le_coby1_then_la1.asm diff --git a/src/dk/camelot64/kickc/asm/fragment/zpby1_lt_coby1_then_la1.asm b/src/dk/camelot64/kickc/asm/fragment/zpby1_lt_coby1_then_la1.asm new file mode 100644 index 000000000..f61f981ea --- /dev/null +++ b/src/dk/camelot64/kickc/asm/fragment/zpby1_lt_coby1_then_la1.asm @@ -0,0 +1,3 @@ +lda {zpby1} +cmp #{coby1} +bcc {la1} diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 b/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 new file mode 100644 index 000000000..fb0fa1827 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 @@ -0,0 +1,55 @@ +// 6502 Assembler Grammar +grammar Asm6502; + +file : + lineSeq EOF + ; + +lineSeq + : line+ + ; + +line + : label? instruction? comment? '\n' + ; + +label + : NAME ':' + ; + +comment + : '//' .*? + ; + +instruction + : MNEMONIC (paramMode)? + ; + +paramMode + : param #modeAbs + | '#' param #modeImm + | param ',x' #modeAbsX + | param ',y' #modeAbsY + | '(' param ')' ',y' #modeIndY + | '(' param ',x' ')' #modeIndX + | '(' param ')' #modeInd + ; + +param + : NAME #paramLabel + | '{' NAME '}' #paramReplace + | NUMINT #paramInt + ; + +MNEMONIC: [A-Za-z][A-Za-z][A-Za-z]; +NUMINT : DECINTEGER | HEXINTEGER | BININTEGER ; +BININTEGER : '0' [bB] BINDIGIT+ | '%' BINDIGIT+ ; +DECINTEGER : DECDIGIT+ ; +HEXINTEGER : ( '$' | '0x' | '0X' ) HEXDIGIT+ ; +fragment BINDIGIT : [0-1]; +fragment DECDIGIT : [0-9]; +fragment HEXDIGIT : [0-9a-fA-F]; +NAME : NAME_START NAME_CHAR* [+-]* ; +fragment NAME_START : [!a-zA-Z_]; +fragment NAME_CHAR : [a-zA-Z0-9_]; +WS : [ \t\r]+ -> skip ; // skip spaces, tabs \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens b/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens new file mode 100644 index 000000000..b5a7d749b --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502.tokens @@ -0,0 +1,27 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +MNEMONIC=11 +NUMINT=12 +BININTEGER=13 +DECINTEGER=14 +HEXINTEGER=15 +NAME=16 +WS=17 +'\n'=1 +':'=2 +'//'=3 +'#'=4 +',x'=5 +',y'=6 +'('=7 +')'=8 +'{'=9 +'}'=10 diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java new file mode 100644 index 000000000..016ed5d50 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseListener.java @@ -0,0 +1,231 @@ +// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7 +package dk.camelot64.kickc.asm.parser; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.tree.ErrorNode; +import org.antlr.v4.runtime.tree.TerminalNode; + +/** + * This class provides an empty implementation of {@link Asm6502Listener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +public class Asm6502BaseListener implements Asm6502Listener { + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterFile(Asm6502Parser.FileContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitFile(Asm6502Parser.FileContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLineSeq(Asm6502Parser.LineSeqContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLineSeq(Asm6502Parser.LineSeqContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLine(Asm6502Parser.LineContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLine(Asm6502Parser.LineContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterLabel(Asm6502Parser.LabelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitLabel(Asm6502Parser.LabelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterComment(Asm6502Parser.CommentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitComment(Asm6502Parser.CommentContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterInstruction(Asm6502Parser.InstructionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitInstruction(Asm6502Parser.InstructionContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeAbs(Asm6502Parser.ModeAbsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeAbs(Asm6502Parser.ModeAbsContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeImm(Asm6502Parser.ModeImmContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeImm(Asm6502Parser.ModeImmContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeIndY(Asm6502Parser.ModeIndYContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeIndY(Asm6502Parser.ModeIndYContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeIndX(Asm6502Parser.ModeIndXContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeIndX(Asm6502Parser.ModeIndXContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterModeInd(Asm6502Parser.ModeIndContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitModeInd(Asm6502Parser.ModeIndContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterParamLabel(Asm6502Parser.ParamLabelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitParamLabel(Asm6502Parser.ParamLabelContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterParamReplace(Asm6502Parser.ParamReplaceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterParamInt(Asm6502Parser.ParamIntContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitParamInt(Asm6502Parser.ParamIntContext ctx) { } + + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void enterEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void exitEveryRule(ParserRuleContext ctx) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitTerminal(TerminalNode node) { } + /** + * {@inheritDoc} + * + *

The default implementation does nothing.

+ */ + @Override public void visitErrorNode(ErrorNode node) { } +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java new file mode 100644 index 000000000..45ae587a2 --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502BaseVisitor.java @@ -0,0 +1,126 @@ +// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7 +package dk.camelot64.kickc.asm.parser; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link Asm6502Visitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class Asm6502BaseVisitor extends AbstractParseTreeVisitor implements Asm6502Visitor { + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitFile(Asm6502Parser.FileContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLineSeq(Asm6502Parser.LineSeqContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLine(Asm6502Parser.LineContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitLabel(Asm6502Parser.LabelContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitComment(Asm6502Parser.CommentContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitInstruction(Asm6502Parser.InstructionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeAbs(Asm6502Parser.ModeAbsContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeImm(Asm6502Parser.ModeImmContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeIndY(Asm6502Parser.ModeIndYContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeIndX(Asm6502Parser.ModeIndXContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitModeInd(Asm6502Parser.ModeIndContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitParamLabel(Asm6502Parser.ParamLabelContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitParamReplace(Asm6502Parser.ParamReplaceContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

+ */ + @Override public T visitParamInt(Asm6502Parser.ParamIntContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java new file mode 100644 index 000000000..84d53e17d --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.java @@ -0,0 +1,152 @@ +// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7 +package dk.camelot64.kickc.asm.parser; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class Asm6502Lexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, MNEMONIC=11, NUMINT=12, BININTEGER=13, DECINTEGER=14, HEXINTEGER=15, + NAME=16, WS=17; + public static String[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }; + + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", + "T__9", "MNEMONIC", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", + "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR", + "WS" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'{'", + "'}'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, "MNEMONIC", + "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public Asm6502Lexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "Asm6502.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getChannelNames() { return channelNames; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\23\u008d\b\1\4\2"+ + "\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+ + "\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+ + "\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\3\2\3\3\3"+ + "\3\3\4\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n"+ + "\3\13\3\13\3\f\3\f\3\f\3\f\3\r\3\r\3\r\5\rN\n\r\3\16\3\16\3\16\6\16S\n"+ + "\16\r\16\16\16T\3\16\3\16\6\16Y\n\16\r\16\16\16Z\5\16]\n\16\3\17\6\17"+ + "`\n\17\r\17\16\17a\3\20\3\20\3\20\3\20\3\20\5\20i\n\20\3\20\6\20l\n\20"+ + "\r\20\16\20m\3\21\3\21\3\22\3\22\3\23\3\23\3\24\3\24\7\24x\n\24\f\24\16"+ + "\24{\13\24\3\24\7\24~\n\24\f\24\16\24\u0081\13\24\3\25\3\25\3\26\3\26"+ + "\3\27\6\27\u0088\n\27\r\27\16\27\u0089\3\27\3\27\2\2\30\3\3\5\4\7\5\t"+ + "\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\2#\2%\2"+ + "\'\22)\2+\2-\23\3\2\13\4\2C\\c|\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch"+ + "\4\2--//\6\2##C\\aac|\6\2\62;C\\aac|\5\2\13\13\17\17\"\"\2\u0093\2\3\3"+ + "\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2"+ + "\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3"+ + "\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2\'\3\2\2\2\2-\3\2\2\2\3"+ + "/\3\2\2\2\5\61\3\2\2\2\7\63\3\2\2\2\t\66\3\2\2\2\138\3\2\2\2\r;\3\2\2"+ + "\2\17>\3\2\2\2\21@\3\2\2\2\23B\3\2\2\2\25D\3\2\2\2\27F\3\2\2\2\31M\3\2"+ + "\2\2\33\\\3\2\2\2\35_\3\2\2\2\37h\3\2\2\2!o\3\2\2\2#q\3\2\2\2%s\3\2\2"+ + "\2\'u\3\2\2\2)\u0082\3\2\2\2+\u0084\3\2\2\2-\u0087\3\2\2\2/\60\7\f\2\2"+ + "\60\4\3\2\2\2\61\62\7<\2\2\62\6\3\2\2\2\63\64\7\61\2\2\64\65\7\61\2\2"+ + "\65\b\3\2\2\2\66\67\7%\2\2\67\n\3\2\2\289\7.\2\29:\7z\2\2:\f\3\2\2\2;"+ + "<\7.\2\2<=\7{\2\2=\16\3\2\2\2>?\7*\2\2?\20\3\2\2\2@A\7+\2\2A\22\3\2\2"+ + "\2BC\7}\2\2C\24\3\2\2\2DE\7\177\2\2E\26\3\2\2\2FG\t\2\2\2GH\t\2\2\2HI"+ + "\t\2\2\2I\30\3\2\2\2JN\5\35\17\2KN\5\37\20\2LN\5\33\16\2MJ\3\2\2\2MK\3"+ + "\2\2\2ML\3\2\2\2N\32\3\2\2\2OP\7\62\2\2PR\t\3\2\2QS\5!\21\2RQ\3\2\2\2"+ + "ST\3\2\2\2TR\3\2\2\2TU\3\2\2\2U]\3\2\2\2VX\7\'\2\2WY\5!\21\2XW\3\2\2\2"+ + "YZ\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[]\3\2\2\2\\O\3\2\2\2\\V\3\2\2\2]\34\3\2"+ + "\2\2^`\5#\22\2_^\3\2\2\2`a\3\2\2\2a_\3\2\2\2ab\3\2\2\2b\36\3\2\2\2ci\7"+ + "&\2\2de\7\62\2\2ei\7z\2\2fg\7\62\2\2gi\7Z\2\2hc\3\2\2\2hd\3\2\2\2hf\3"+ + "\2\2\2ik\3\2\2\2jl\5%\23\2kj\3\2\2\2lm\3\2\2\2mk\3\2\2\2mn\3\2\2\2n \3"+ + "\2\2\2op\t\4\2\2p\"\3\2\2\2qr\t\5\2\2r$\3\2\2\2st\t\6\2\2t&\3\2\2\2uy"+ + "\5)\25\2vx\5+\26\2wv\3\2\2\2x{\3\2\2\2yw\3\2\2\2yz\3\2\2\2z\177\3\2\2"+ + "\2{y\3\2\2\2|~\t\7\2\2}|\3\2\2\2~\u0081\3\2\2\2\177}\3\2\2\2\177\u0080"+ + "\3\2\2\2\u0080(\3\2\2\2\u0081\177\3\2\2\2\u0082\u0083\t\b\2\2\u0083*\3"+ + "\2\2\2\u0084\u0085\t\t\2\2\u0085,\3\2\2\2\u0086\u0088\t\n\2\2\u0087\u0086"+ + "\3\2\2\2\u0088\u0089\3\2\2\2\u0089\u0087\3\2\2\2\u0089\u008a\3\2\2\2\u008a"+ + "\u008b\3\2\2\2\u008b\u008c\b\27\2\2\u008c.\3\2\2\2\r\2MTZ\\ahmy\177\u0089"+ + "\3\b\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens new file mode 100644 index 000000000..b5a7d749b --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Lexer.tokens @@ -0,0 +1,27 @@ +T__0=1 +T__1=2 +T__2=3 +T__3=4 +T__4=5 +T__5=6 +T__6=7 +T__7=8 +T__8=9 +T__9=10 +MNEMONIC=11 +NUMINT=12 +BININTEGER=13 +DECINTEGER=14 +HEXINTEGER=15 +NAME=16 +WS=17 +'\n'=1 +':'=2 +'//'=3 +'#'=4 +',x'=5 +',y'=6 +'('=7 +')'=8 +'{'=9 +'}'=10 diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java new file mode 100644 index 000000000..4fd06e0bd --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Listener.java @@ -0,0 +1,190 @@ +// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7 +package dk.camelot64.kickc.asm.parser; +import org.antlr.v4.runtime.tree.ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@link Asm6502Parser}. + */ +public interface Asm6502Listener extends ParseTreeListener { + /** + * Enter a parse tree produced by {@link Asm6502Parser#file}. + * @param ctx the parse tree + */ + void enterFile(Asm6502Parser.FileContext ctx); + /** + * Exit a parse tree produced by {@link Asm6502Parser#file}. + * @param ctx the parse tree + */ + void exitFile(Asm6502Parser.FileContext ctx); + /** + * Enter a parse tree produced by {@link Asm6502Parser#lineSeq}. + * @param ctx the parse tree + */ + void enterLineSeq(Asm6502Parser.LineSeqContext ctx); + /** + * Exit a parse tree produced by {@link Asm6502Parser#lineSeq}. + * @param ctx the parse tree + */ + void exitLineSeq(Asm6502Parser.LineSeqContext ctx); + /** + * Enter a parse tree produced by {@link Asm6502Parser#line}. + * @param ctx the parse tree + */ + void enterLine(Asm6502Parser.LineContext ctx); + /** + * Exit a parse tree produced by {@link Asm6502Parser#line}. + * @param ctx the parse tree + */ + void exitLine(Asm6502Parser.LineContext ctx); + /** + * Enter a parse tree produced by {@link Asm6502Parser#label}. + * @param ctx the parse tree + */ + void enterLabel(Asm6502Parser.LabelContext ctx); + /** + * Exit a parse tree produced by {@link Asm6502Parser#label}. + * @param ctx the parse tree + */ + void exitLabel(Asm6502Parser.LabelContext ctx); + /** + * Enter a parse tree produced by {@link Asm6502Parser#comment}. + * @param ctx the parse tree + */ + void enterComment(Asm6502Parser.CommentContext ctx); + /** + * Exit a parse tree produced by {@link Asm6502Parser#comment}. + * @param ctx the parse tree + */ + void exitComment(Asm6502Parser.CommentContext ctx); + /** + * Enter a parse tree produced by {@link Asm6502Parser#instruction}. + * @param ctx the parse tree + */ + void enterInstruction(Asm6502Parser.InstructionContext ctx); + /** + * Exit a parse tree produced by {@link Asm6502Parser#instruction}. + * @param ctx the parse tree + */ + void exitInstruction(Asm6502Parser.InstructionContext ctx); + /** + * Enter a parse tree produced by the {@code modeAbs} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeAbs(Asm6502Parser.ModeAbsContext ctx); + /** + * Exit a parse tree produced by the {@code modeAbs} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeAbs(Asm6502Parser.ModeAbsContext ctx); + /** + * Enter a parse tree produced by the {@code modeImm} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeImm(Asm6502Parser.ModeImmContext ctx); + /** + * Exit a parse tree produced by the {@code modeImm} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeImm(Asm6502Parser.ModeImmContext ctx); + /** + * Enter a parse tree produced by the {@code modeAbsX} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeAbsX(Asm6502Parser.ModeAbsXContext ctx); + /** + * Exit a parse tree produced by the {@code modeAbsX} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeAbsX(Asm6502Parser.ModeAbsXContext ctx); + /** + * Enter a parse tree produced by the {@code modeAbsY} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeAbsY(Asm6502Parser.ModeAbsYContext ctx); + /** + * Exit a parse tree produced by the {@code modeAbsY} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeAbsY(Asm6502Parser.ModeAbsYContext ctx); + /** + * Enter a parse tree produced by the {@code modeIndY} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeIndY(Asm6502Parser.ModeIndYContext ctx); + /** + * Exit a parse tree produced by the {@code modeIndY} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeIndY(Asm6502Parser.ModeIndYContext ctx); + /** + * Enter a parse tree produced by the {@code modeIndX} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeIndX(Asm6502Parser.ModeIndXContext ctx); + /** + * Exit a parse tree produced by the {@code modeIndX} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeIndX(Asm6502Parser.ModeIndXContext ctx); + /** + * Enter a parse tree produced by the {@code modeInd} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void enterModeInd(Asm6502Parser.ModeIndContext ctx); + /** + * Exit a parse tree produced by the {@code modeInd} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + */ + void exitModeInd(Asm6502Parser.ModeIndContext ctx); + /** + * Enter a parse tree produced by the {@code paramLabel} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + */ + void enterParamLabel(Asm6502Parser.ParamLabelContext ctx); + /** + * Exit a parse tree produced by the {@code paramLabel} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + */ + void exitParamLabel(Asm6502Parser.ParamLabelContext ctx); + /** + * Enter a parse tree produced by the {@code paramReplace} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + */ + void enterParamReplace(Asm6502Parser.ParamReplaceContext ctx); + /** + * Exit a parse tree produced by the {@code paramReplace} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + */ + void exitParamReplace(Asm6502Parser.ParamReplaceContext ctx); + /** + * Enter a parse tree produced by the {@code paramInt} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + */ + void enterParamInt(Asm6502Parser.ParamIntContext ctx); + /** + * Exit a parse tree produced by the {@code paramInt} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + */ + void exitParamInt(Asm6502Parser.ParamIntContext ctx); +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java new file mode 100644 index 000000000..1650ae77c --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Parser.java @@ -0,0 +1,821 @@ +// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7 +package dk.camelot64.kickc.asm.parser; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class Asm6502Parser extends Parser { + static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, + T__9=10, MNEMONIC=11, NUMINT=12, BININTEGER=13, DECINTEGER=14, HEXINTEGER=15, + NAME=16, WS=17; + public static final int + RULE_file = 0, RULE_lineSeq = 1, RULE_line = 2, RULE_label = 3, RULE_comment = 4, + RULE_instruction = 5, RULE_paramMode = 6, RULE_param = 7; + public static final String[] ruleNames = { + "file", "lineSeq", "line", "label", "comment", "instruction", "paramMode", + "param" + }; + + private static final String[] _LITERAL_NAMES = { + null, "'\n'", "':'", "'//'", "'#'", "',x'", "',y'", "'('", "')'", "'{'", + "'}'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, null, null, null, null, null, null, null, null, null, "MNEMONIC", + "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER", "NAME", "WS" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "Asm6502.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + public Asm6502Parser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class FileContext extends ParserRuleContext { + public LineSeqContext lineSeq() { + return getRuleContext(LineSeqContext.class,0); + } + public TerminalNode EOF() { return getToken(Asm6502Parser.EOF, 0); } + public FileContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_file; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterFile(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitFile(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitFile(this); + else return visitor.visitChildren(this); + } + } + + public final FileContext file() throws RecognitionException { + FileContext _localctx = new FileContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_file); + try { + enterOuterAlt(_localctx, 1); + { + setState(16); + lineSeq(); + setState(17); + match(EOF); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LineSeqContext extends ParserRuleContext { + public List line() { + return getRuleContexts(LineContext.class); + } + public LineContext line(int i) { + return getRuleContext(LineContext.class,i); + } + public LineSeqContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_lineSeq; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterLineSeq(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitLineSeq(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitLineSeq(this); + else return visitor.visitChildren(this); + } + } + + public final LineSeqContext lineSeq() throws RecognitionException { + LineSeqContext _localctx = new LineSeqContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_lineSeq); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(20); + _errHandler.sync(this); + _la = _input.LA(1); + do { + { + { + setState(19); + line(); + } + } + setState(22); + _errHandler.sync(this); + _la = _input.LA(1); + } while ( (((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__2) | (1L << MNEMONIC) | (1L << NAME))) != 0) ); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LineContext extends ParserRuleContext { + public LabelContext label() { + return getRuleContext(LabelContext.class,0); + } + public InstructionContext instruction() { + return getRuleContext(InstructionContext.class,0); + } + public CommentContext comment() { + return getRuleContext(CommentContext.class,0); + } + public LineContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_line; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterLine(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitLine(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitLine(this); + else return visitor.visitChildren(this); + } + } + + public final LineContext line() throws RecognitionException { + LineContext _localctx = new LineContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_line); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(25); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==NAME) { + { + setState(24); + label(); + } + } + + setState(28); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==MNEMONIC) { + { + setState(27); + instruction(); + } + } + + setState(31); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==T__2) { + { + setState(30); + comment(); + } + } + + setState(33); + match(T__0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class LabelContext extends ParserRuleContext { + public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); } + public LabelContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_label; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterLabel(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitLabel(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitLabel(this); + else return visitor.visitChildren(this); + } + } + + public final LabelContext label() throws RecognitionException { + LabelContext _localctx = new LabelContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_label); + try { + enterOuterAlt(_localctx, 1); + { + setState(35); + match(NAME); + setState(36); + match(T__1); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class CommentContext extends ParserRuleContext { + public CommentContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_comment; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterComment(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitComment(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitComment(this); + else return visitor.visitChildren(this); + } + } + + public final CommentContext comment() throws RecognitionException { + CommentContext _localctx = new CommentContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_comment); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(38); + match(T__2); + setState(42); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,4,_ctx); + while ( _alt!=1 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1+1 ) { + { + { + setState(39); + matchWildcard(); + } + } + } + setState(44); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,4,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class InstructionContext extends ParserRuleContext { + public TerminalNode MNEMONIC() { return getToken(Asm6502Parser.MNEMONIC, 0); } + public ParamModeContext paramMode() { + return getRuleContext(ParamModeContext.class,0); + } + public InstructionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_instruction; } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterInstruction(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitInstruction(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitInstruction(this); + else return visitor.visitChildren(this); + } + } + + public final InstructionContext instruction() throws RecognitionException { + InstructionContext _localctx = new InstructionContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_instruction); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(45); + match(MNEMONIC); + setState(47); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__6) | (1L << T__8) | (1L << NUMINT) | (1L << NAME))) != 0)) { + { + setState(46); + paramMode(); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ParamModeContext extends ParserRuleContext { + public ParamModeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_paramMode; } + + public ParamModeContext() { } + public void copyFrom(ParamModeContext ctx) { + super.copyFrom(ctx); + } + } + public static class ModeIndXContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeIndXContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeIndX(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeIndX(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeIndX(this); + else return visitor.visitChildren(this); + } + } + public static class ModeImmContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeImmContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeImm(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeImm(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeImm(this); + else return visitor.visitChildren(this); + } + } + public static class ModeIndYContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeIndYContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeIndY(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeIndY(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeIndY(this); + else return visitor.visitChildren(this); + } + } + public static class ModeAbsYContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeAbsYContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeAbsY(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeAbsY(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeAbsY(this); + else return visitor.visitChildren(this); + } + } + public static class ModeIndContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeIndContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeInd(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeInd(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeInd(this); + else return visitor.visitChildren(this); + } + } + public static class ModeAbsContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeAbsContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeAbs(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeAbs(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeAbs(this); + else return visitor.visitChildren(this); + } + } + public static class ModeAbsXContext extends ParamModeContext { + public ParamContext param() { + return getRuleContext(ParamContext.class,0); + } + public ModeAbsXContext(ParamModeContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterModeAbsX(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitModeAbsX(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitModeAbsX(this); + else return visitor.visitChildren(this); + } + } + + public final ParamModeContext paramMode() throws RecognitionException { + ParamModeContext _localctx = new ParamModeContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_paramMode); + try { + setState(72); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) { + case 1: + _localctx = new ModeAbsContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(49); + param(); + } + break; + case 2: + _localctx = new ModeImmContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(50); + match(T__3); + setState(51); + param(); + } + break; + case 3: + _localctx = new ModeAbsXContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(52); + param(); + setState(53); + match(T__4); + } + break; + case 4: + _localctx = new ModeAbsYContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(55); + param(); + setState(56); + match(T__5); + } + break; + case 5: + _localctx = new ModeIndYContext(_localctx); + enterOuterAlt(_localctx, 5); + { + setState(58); + match(T__6); + setState(59); + param(); + setState(60); + match(T__7); + setState(61); + match(T__5); + } + break; + case 6: + _localctx = new ModeIndXContext(_localctx); + enterOuterAlt(_localctx, 6); + { + setState(63); + match(T__6); + setState(64); + param(); + setState(65); + match(T__4); + setState(66); + match(T__7); + } + break; + case 7: + _localctx = new ModeIndContext(_localctx); + enterOuterAlt(_localctx, 7); + { + setState(68); + match(T__6); + setState(69); + param(); + setState(70); + match(T__7); + } + break; + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ParamContext extends ParserRuleContext { + public ParamContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_param; } + + public ParamContext() { } + public void copyFrom(ParamContext ctx) { + super.copyFrom(ctx); + } + } + public static class ParamReplaceContext extends ParamContext { + public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); } + public ParamReplaceContext(ParamContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamReplace(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamReplace(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitParamReplace(this); + else return visitor.visitChildren(this); + } + } + public static class ParamIntContext extends ParamContext { + public TerminalNode NUMINT() { return getToken(Asm6502Parser.NUMINT, 0); } + public ParamIntContext(ParamContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamInt(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamInt(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitParamInt(this); + else return visitor.visitChildren(this); + } + } + public static class ParamLabelContext extends ParamContext { + public TerminalNode NAME() { return getToken(Asm6502Parser.NAME, 0); } + public ParamLabelContext(ParamContext ctx) { copyFrom(ctx); } + @Override + public void enterRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).enterParamLabel(this); + } + @Override + public void exitRule(ParseTreeListener listener) { + if ( listener instanceof Asm6502Listener ) ((Asm6502Listener)listener).exitParamLabel(this); + } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof Asm6502Visitor ) return ((Asm6502Visitor)visitor).visitParamLabel(this); + else return visitor.visitChildren(this); + } + } + + public final ParamContext param() throws RecognitionException { + ParamContext _localctx = new ParamContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_param); + try { + setState(79); + _errHandler.sync(this); + switch (_input.LA(1)) { + case NAME: + _localctx = new ParamLabelContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(74); + match(NAME); + } + break; + case T__8: + _localctx = new ParamReplaceContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(75); + match(T__8); + setState(76); + match(NAME); + setState(77); + match(T__9); + } + break; + case NUMINT: + _localctx = new ParamIntContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(78); + match(NUMINT); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\23T\4\2\t\2\4\3\t"+ + "\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\3\2\3\2\3\2\3\3\6\3"+ + "\27\n\3\r\3\16\3\30\3\4\5\4\34\n\4\3\4\5\4\37\n\4\3\4\5\4\"\n\4\3\4\3"+ + "\4\3\5\3\5\3\5\3\6\3\6\7\6+\n\6\f\6\16\6.\13\6\3\7\3\7\5\7\62\n\7\3\b"+ + "\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ + "\b\3\b\3\b\3\b\3\b\5\bK\n\b\3\t\3\t\3\t\3\t\3\t\5\tR\n\t\3\t\3,\2\n\2"+ + "\4\6\b\n\f\16\20\2\2\2Y\2\22\3\2\2\2\4\26\3\2\2\2\6\33\3\2\2\2\b%\3\2"+ + "\2\2\n(\3\2\2\2\f/\3\2\2\2\16J\3\2\2\2\20Q\3\2\2\2\22\23\5\4\3\2\23\24"+ + "\7\2\2\3\24\3\3\2\2\2\25\27\5\6\4\2\26\25\3\2\2\2\27\30\3\2\2\2\30\26"+ + "\3\2\2\2\30\31\3\2\2\2\31\5\3\2\2\2\32\34\5\b\5\2\33\32\3\2\2\2\33\34"+ + "\3\2\2\2\34\36\3\2\2\2\35\37\5\f\7\2\36\35\3\2\2\2\36\37\3\2\2\2\37!\3"+ + "\2\2\2 \"\5\n\6\2! \3\2\2\2!\"\3\2\2\2\"#\3\2\2\2#$\7\3\2\2$\7\3\2\2\2"+ + "%&\7\22\2\2&\'\7\4\2\2\'\t\3\2\2\2(,\7\5\2\2)+\13\2\2\2*)\3\2\2\2+.\3"+ + "\2\2\2,-\3\2\2\2,*\3\2\2\2-\13\3\2\2\2.,\3\2\2\2/\61\7\r\2\2\60\62\5\16"+ + "\b\2\61\60\3\2\2\2\61\62\3\2\2\2\62\r\3\2\2\2\63K\5\20\t\2\64\65\7\6\2"+ + "\2\65K\5\20\t\2\66\67\5\20\t\2\678\7\7\2\28K\3\2\2\29:\5\20\t\2:;\7\b"+ + "\2\2;K\3\2\2\2<=\7\t\2\2=>\5\20\t\2>?\7\n\2\2?@\7\b\2\2@K\3\2\2\2AB\7"+ + "\t\2\2BC\5\20\t\2CD\7\7\2\2DE\7\n\2\2EK\3\2\2\2FG\7\t\2\2GH\5\20\t\2H"+ + "I\7\n\2\2IK\3\2\2\2J\63\3\2\2\2J\64\3\2\2\2J\66\3\2\2\2J9\3\2\2\2J<\3"+ + "\2\2\2JA\3\2\2\2JF\3\2\2\2K\17\3\2\2\2LR\7\22\2\2MN\7\13\2\2NO\7\22\2"+ + "\2OR\7\f\2\2PR\7\16\2\2QL\3\2\2\2QM\3\2\2\2QP\3\2\2\2R\21\3\2\2\2\n\30"+ + "\33\36!,\61JQ"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java b/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java new file mode 100644 index 000000000..6a927296d --- /dev/null +++ b/src/dk/camelot64/kickc/asm/parser/Asm6502Visitor.java @@ -0,0 +1,119 @@ +// Generated from /Users/jespergravgaard/c64/src/kickc/src/dk/camelot64/kickc/asm/parser/Asm6502.g4 by ANTLR 4.7 +package dk.camelot64.kickc.asm.parser; +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link Asm6502Parser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface Asm6502Visitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link Asm6502Parser#file}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFile(Asm6502Parser.FileContext ctx); + /** + * Visit a parse tree produced by {@link Asm6502Parser#lineSeq}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLineSeq(Asm6502Parser.LineSeqContext ctx); + /** + * Visit a parse tree produced by {@link Asm6502Parser#line}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLine(Asm6502Parser.LineContext ctx); + /** + * Visit a parse tree produced by {@link Asm6502Parser#label}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitLabel(Asm6502Parser.LabelContext ctx); + /** + * Visit a parse tree produced by {@link Asm6502Parser#comment}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComment(Asm6502Parser.CommentContext ctx); + /** + * Visit a parse tree produced by {@link Asm6502Parser#instruction}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInstruction(Asm6502Parser.InstructionContext ctx); + /** + * Visit a parse tree produced by the {@code modeAbs} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeAbs(Asm6502Parser.ModeAbsContext ctx); + /** + * Visit a parse tree produced by the {@code modeImm} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeImm(Asm6502Parser.ModeImmContext ctx); + /** + * Visit a parse tree produced by the {@code modeAbsX} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeAbsX(Asm6502Parser.ModeAbsXContext ctx); + /** + * Visit a parse tree produced by the {@code modeAbsY} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeAbsY(Asm6502Parser.ModeAbsYContext ctx); + /** + * Visit a parse tree produced by the {@code modeIndY} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeIndY(Asm6502Parser.ModeIndYContext ctx); + /** + * Visit a parse tree produced by the {@code modeIndX} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeIndX(Asm6502Parser.ModeIndXContext ctx); + /** + * Visit a parse tree produced by the {@code modeInd} + * labeled alternative in {@link Asm6502Parser#paramMode}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitModeInd(Asm6502Parser.ModeIndContext ctx); + /** + * Visit a parse tree produced by the {@code paramLabel} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitParamLabel(Asm6502Parser.ParamLabelContext ctx); + /** + * Visit a parse tree produced by the {@code paramReplace} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitParamReplace(Asm6502Parser.ParamReplaceContext ctx); + /** + * Visit a parse tree produced by the {@code paramInt} + * labeled alternative in {@link Asm6502Parser#param}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitParamInt(Asm6502Parser.ParamIntContext ctx); +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java index be44c4180..8319c343b 100644 --- a/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/Pass3RegisterAllocation.java @@ -22,10 +22,10 @@ public class Pass3RegisterAllocation { allocation.allocate(var, new RegisterAllocation.RegisterZpBool(currentZp++)); } } - allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX()); - allocation.allocate(symbols.getVariable("n1#1"), new RegisterAllocation.RegisterZpByte(8)); - allocation.allocate(symbols.getVariable("n1#2"), new RegisterAllocation.RegisterZpByte(8)); +// allocation.allocate(symbols.getVariable("i#1"), RegisterAllocation.getRegisterX()); +// allocation.allocate(symbols.getVariable("i#3"), RegisterAllocation.getRegisterX()); +// allocation.allocate(symbols.getVariable("n1#1"), new RegisterAllocation.RegisterZpByte(8)); +// allocation.allocate(symbols.getVariable("n1#2"), new RegisterAllocation.RegisterZpByte(8)); symbols.setAllocation(allocation); } diff --git a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java index c5f7a5ebc..7c341099c 100644 --- a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java +++ b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java @@ -1,5 +1,8 @@ package dk.camelot64.kickc.icl; +import dk.camelot64.kickc.asm.AsmFragment; +import dk.camelot64.kickc.asm.AsmSequence; + import java.util.List; /** @@ -27,12 +30,10 @@ public class Pass4CodeGeneration { // Generate exit ControlFlowBlock defaultSuccessor = block.getDefaultSuccessor(); if (defaultSuccessor != null) { - if (defaultSuccessor.getPredecessors().size() > 1) { - String label = defaultSuccessor.getLabel().getName() + "_from_" + block.getLabel().getName(); - genAsmJump(asm, label); - } else { - genAsmJump(asm, defaultSuccessor.getLabel().getName()); + if(defaultSuccessor.getStatements().size()>0 && defaultSuccessor.getStatements().get(0) instanceof StatementPhi) { + genBlockPhiTransition(asm, block, defaultSuccessor); } + genAsmJump(asm, defaultSuccessor.getLabel().getName()); } } return asm; @@ -64,30 +65,45 @@ public class Pass4CodeGeneration { List statements = block.getStatements(); if (statements.size() > 0 && (statements.get(0) instanceof StatementPhi)) { for (ControlFlowBlock predecessor : block.getPredecessors()) { - genBlockEntryPoint(asm, block, predecessor); + if(block.equals(predecessor.getConditionalSuccessor())) { + genBlockPhiTransition(asm, predecessor, block); + genAsmJump(asm, block.getLabel().getName()); + } } } } - private void genBlockEntryPoint(AsmSequence asm, ControlFlowBlock block, ControlFlowBlock predecessor) { - genAsmLabel(asm, block.getLabel().getName() + "_from_" + predecessor.getLabel().getName()); - for (Statement statement : block.getStatements()) { + private void genBlockPhiTransition(AsmSequence asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) { + genAsmLabel(asm, toBlock.getLabel().getName() + "_from_" + fromBlock.getLabel().getName()); + for (Statement statement : toBlock.getStatements()) { if (!(statement instanceof StatementPhi)) { // No more phi statements to handle break; } StatementPhi phi = (StatementPhi) statement; for (StatementPhi.PreviousSymbol previousSymbol : phi.getPreviousVersions()) { - if (previousSymbol.getBlock().equals(predecessor)) { + if (previousSymbol.getBlock().equals(fromBlock)) { genAsmMove(asm, phi.getLValue(), previousSymbol.getRValue()); break; } } } - genAsmJump(asm, block.getLabel().getName()); + } + + private RegisterAllocation.Register getRegister(RValue rValue) { + if(rValue instanceof Variable) { + return symbols.getRegister((Variable) rValue); + } else { + return null; + } } private void genAsmMove(AsmSequence asm, LValue lValue, RValue rValue) { + if(getRegister(lValue).equals(getRegister(rValue))) { + // Do not move from register to itself + asm.addAsm(" // " + lValue + " = " + rValue + " // register copy " ); + return; + } AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols); asm.addAsm(" // " + lValue + " = " + rValue + " // " + asmFragment.getSignature()); asmFragment.generateAsm(asm); diff --git a/src/dk/camelot64/kickc/icl/RegisterAllocation.java b/src/dk/camelot64/kickc/icl/RegisterAllocation.java index ba86d0143..683be78ea 100644 --- a/src/dk/camelot64/kickc/icl/RegisterAllocation.java +++ b/src/dk/camelot64/kickc/icl/RegisterAllocation.java @@ -61,6 +61,21 @@ public class RegisterAllocation { public String toString() { return "zp byte:"+zp; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RegisterZpByte that = (RegisterZpByte) o; + + return zp == that.zp; + } + + @Override + public int hashCode() { + return zp; + } } /** A zero page address used as a register for a boolean variable. */ @@ -84,6 +99,21 @@ public class RegisterAllocation { public String toString() { return "zp bool:"+zp; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RegisterZpBool that = (RegisterZpBool) o; + + return zp == that.zp; + } + + @Override + public int hashCode() { + return zp; + } } /** The X register. */ @@ -97,6 +127,13 @@ public class RegisterAllocation { public String toString() { return "reg byte x"; } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + return true; + } } public static Register getRegisterX() { diff --git a/src/dk/camelot64/kickc/icl/asm/xby=coby1.asm b/src/dk/camelot64/kickc/icl/asm/xby=coby1.asm deleted file mode 100644 index 8bc1f4465..000000000 --- a/src/dk/camelot64/kickc/icl/asm/xby=coby1.asm +++ /dev/null @@ -1 +0,0 @@ -ldx #{coby1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/asm/xby=xby_minus_1.asm b/src/dk/camelot64/kickc/icl/asm/xby=xby_minus_1.asm deleted file mode 100644 index 23e2d0ff8..000000000 --- a/src/dk/camelot64/kickc/icl/asm/xby=xby_minus_1.asm +++ /dev/null @@ -1 +0,0 @@ -dex \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/asm/xby_gt_0_then_la1.asm b/src/dk/camelot64/kickc/icl/asm/xby_gt_0_then_la1.asm deleted file mode 100644 index 0f99f0508..000000000 --- a/src/dk/camelot64/kickc/icl/asm/xby_gt_0_then_la1.asm +++ /dev/null @@ -1,2 +0,0 @@ -cpx #0 -bne {la1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_gt_coby1.asm b/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_gt_coby1.asm deleted file mode 100644 index 3d43f7867..000000000 --- a/src/dk/camelot64/kickc/icl/asm/zpbo1=zpby1_gt_coby1.asm +++ /dev/null @@ -1,8 +0,0 @@ -lda {zpby1} -cmp #{coby1} -beq !f+ -bcs !t+ -!f: lda #0 -jmp !d+ -!t: lda #$ff -!d: sta {zpbo1} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index 15ad1127e..ea302c408 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -1,6 +1,7 @@ package dk.camelot64.kickc.test; import dk.camelot64.kickc.icl.*; +import dk.camelot64.kickc.asm.AsmSequence; import dk.camelot64.kickc.parser.KickCLexer; import dk.camelot64.kickc.parser.KickCParser; import org.antlr.v4.runtime.CharStream;