From 0ba8ac742e74549fb44b0d5b4dcb4b7a274a511c Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 21 May 2017 10:56:26 +0200 Subject: [PATCH] Retired old ASM sequence for new ASM program --- .../kickc/asm/AsmAddressingMode.java | 22 ++++---- src/dk/camelot64/kickc/asm/AsmComment.java | 1 + src/dk/camelot64/kickc/asm/AsmFragment.java | 17 +++---- .../camelot64/kickc/asm/AsmInstuctionSet.java | 33 ++++++++++-- src/dk/camelot64/kickc/asm/AsmLabel.java | 2 +- src/dk/camelot64/kickc/asm/AsmProgram.java | 26 ++++++++++ src/dk/camelot64/kickc/asm/AsmSequence.java | 48 ----------------- src/dk/camelot64/kickc/icl/NumberParser.java | 2 +- .../kickc/icl/Pass4CodeGeneration.java | 51 +++++++------------ src/dk/camelot64/kickc/test/Main.java | 6 +-- 10 files changed, 97 insertions(+), 111 deletions(-) delete mode 100644 src/dk/camelot64/kickc/asm/AsmSequence.java diff --git a/src/dk/camelot64/kickc/asm/AsmAddressingMode.java b/src/dk/camelot64/kickc/asm/AsmAddressingMode.java index e8bb8af4c..3a216684d 100644 --- a/src/dk/camelot64/kickc/asm/AsmAddressingMode.java +++ b/src/dk/camelot64/kickc/asm/AsmAddressingMode.java @@ -3,17 +3,17 @@ 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); + IMM("#imm", "%i.imm #%p", 2), + ZP("zp", "%i.zp %p", 2), + ZPX("zp,x", "%i.zpx %p,x", 2), + ZPY("zp,y", "%i.zpy %p,y", 2), + ABS("abs", "%i.abs %p", 3), + ABX("abs,x", "%i.abx %p,x", 3), + ABY("abs,y", "%i.aby %p,y", 4), + IZX("(zp,x)", "%i.izx (%p,x)", 2), + IZY("(zp),y", "%i.izy (%p),y", 2), + REL("rel", "%i.rel %p", 2), + IND("(ind)", "%i.ind (%p)", 3); private String name; diff --git a/src/dk/camelot64/kickc/asm/AsmComment.java b/src/dk/camelot64/kickc/asm/AsmComment.java index 6f00c415e..0faddeaad 100644 --- a/src/dk/camelot64/kickc/asm/AsmComment.java +++ b/src/dk/camelot64/kickc/asm/AsmComment.java @@ -32,4 +32,5 @@ public class AsmComment implements AsmLine { public String getAsm() { return "// "+comment; } + } diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index 90c321b35..c1f0aa66f 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -11,8 +11,6 @@ import java.io.InputStream; import java.net.URL; import java.util.HashMap; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * Code Generation Fragment that can handle loading of fragment file and binding of values / registers @@ -233,19 +231,19 @@ public class AsmFragment { * * @param asm The assembler sequence to generate into. */ - public void generateAsm(AsmSequence asm) { + public void generate(AsmProgram asm) { String signature = this.getSignature(); ClassLoader classLoader = this.getClass().getClassLoader(); 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); + asm.addComment("Fragment not found: " + signature); return; } try { InputStream fragmentStream = fragmentResource.openStream(); - Asm6502Lexer lexer = new Asm6502Lexer(new ANTLRInputStream(fragmentStream)); + Asm6502Lexer lexer = new Asm6502Lexer(CharStreams.fromStream(fragmentStream)); Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer)); parser.addErrorListener(new BaseErrorListener() { @Override @@ -255,11 +253,8 @@ public class AsmFragment { }); parser.setBuildParseTree(true); Asm6502Parser.FileContext file = parser.file(); - AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(fragmentResource); + AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(fragmentResource, asm); asmSequenceGenerator.generate(file); - for (AsmLine asmLine : asmSequenceGenerator.program.getLines()) { - asm.addAsm(" "+asmLine.getAsm()); - } fragmentStream.close(); } catch (IOException e) { throw new RuntimeException("Error reading code fragment " + fragmentResource); @@ -308,7 +303,7 @@ public class AsmFragment { Asm6502Parser.ParamModeContext paramModeCtx = ctx.paramMode(); AsmInstruction instruction; if(paramModeCtx==null) { - AsmInstructionType type = AsmInstuctionSet.getInstructionType(ctx.MNEMONIC().getText(), AsmAddressingMode.NON); + AsmInstructionType type = AsmInstuctionSet.getInstructionType(ctx.MNEMONIC().getText(), AsmAddressingMode.NON, null); instruction = new AsmInstruction(type, null, 1); } else { instruction = (AsmInstruction) this.visit(paramModeCtx); @@ -360,7 +355,7 @@ public class AsmFragment { 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); + AsmInstructionType type = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode, parameter); return new AsmInstruction(type, parameter, 1); } diff --git a/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java b/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java index 4ad232b2c..889078ad8 100644 --- a/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java +++ b/src/dk/camelot64/kickc/asm/AsmInstuctionSet.java @@ -1,5 +1,7 @@ package dk.camelot64.kickc.asm; +import dk.camelot64.kickc.icl.NumberParser; + import java.util.ArrayList; import java.util.List; @@ -10,14 +12,37 @@ 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)) { + public static AsmInstructionType getInstructionType(String mnemonic, AsmAddressingMode mode, String parameter) { + AsmInstructionType type = null; + if (AsmAddressingMode.ABS.equals(mode) && isZp(parameter)) { + type = set.getType(mnemonic, AsmAddressingMode.ZP); + } + if (AsmAddressingMode.ABX.equals(mode) && isZp(parameter)) { + type = set.getType(mnemonic, AsmAddressingMode.ZPX); + } + if (AsmAddressingMode.ABY.equals(mode) && isZp(parameter)) { + type = set.getType(mnemonic, AsmAddressingMode.ZPY); + } + if (type == null) { + type = set.getType(mnemonic, mode); + } + if (type == null && AsmAddressingMode.ABS.equals(mode)) { type = set.getType(mnemonic, AsmAddressingMode.REL); } return type; } + private static boolean isZp(String parameter) { + Number number = null; + if(parameter!=null) { + try { + number = NumberParser.parseLiteral(parameter); + } catch (NumberFormatException e) { + // ignore + } + } + return (number != null && number.intValue()<256 && number.intValue()>=0); + } private List instructions; @@ -302,7 +327,7 @@ public class AsmInstuctionSet { public AsmInstructionType getType(String mnemonic, AsmAddressingMode addressingMode) { for (AsmInstructionType candidate : instructions) { - if(candidate.getMnemnonic().equals(mnemonic.toLowerCase()) && candidate.getAddressingMode().equals(addressingMode)) { + if (candidate.getMnemnonic().equals(mnemonic.toLowerCase()) && candidate.getAddressingMode().equals(addressingMode)) { return candidate; } } diff --git a/src/dk/camelot64/kickc/asm/AsmLabel.java b/src/dk/camelot64/kickc/asm/AsmLabel.java index 622a4803f..6138e9182 100644 --- a/src/dk/camelot64/kickc/asm/AsmLabel.java +++ b/src/dk/camelot64/kickc/asm/AsmLabel.java @@ -31,6 +31,6 @@ public class AsmLabel implements AsmLine { @Override public String getAsm() { - return ":"+label; + return label+":"; } } diff --git a/src/dk/camelot64/kickc/asm/AsmProgram.java b/src/dk/camelot64/kickc/asm/AsmProgram.java index 1c7d850e7..875364a93 100644 --- a/src/dk/camelot64/kickc/asm/AsmProgram.java +++ b/src/dk/camelot64/kickc/asm/AsmProgram.java @@ -19,4 +19,30 @@ public class AsmProgram { public void addLine(AsmLine line) { lines.add(line); } + + public void addComment(String comment) { + addLine(new AsmComment(comment)); + } + + public void addLabel(String label) { + addLine(new AsmLabel(label)); + } + + public void addInstruction(String mnemonic, AsmAddressingMode addressingMode, String parameter) { + AsmInstructionType instructionType = AsmInstuctionSet.getInstructionType(mnemonic, addressingMode, parameter); + addLine(new AsmInstruction(instructionType, parameter, 1)); + } + + @Override + public String toString() { + StringBuffer out = new StringBuffer(); + for (AsmLine line : lines) { + if(line instanceof AsmComment || line instanceof AsmInstruction) { + out.append(" "); + } + out.append(line.getAsm()+"\n"); + } + return out.toString(); + } + } diff --git a/src/dk/camelot64/kickc/asm/AsmSequence.java b/src/dk/camelot64/kickc/asm/AsmSequence.java deleted file mode 100644 index cabd2c085..000000000 --- a/src/dk/camelot64/kickc/asm/AsmSequence.java +++ /dev/null @@ -1,48 +0,0 @@ -package dk.camelot64.kickc.asm; - -import java.util.ArrayList; -import java.util.List; - -/** A sequence of assembler code. */ -public class AsmSequence { - - private List sequence; - - public AsmSequence() { - this.sequence = new ArrayList<>(); - } - - public List getSequence() { - return sequence; - } - - public void addAsm(String asm) { - sequence.add(new AsmStatement(asm)); - } - - public class AsmStatement { - private String asm; - - public AsmStatement(String asm) { - this.asm = asm; - } - - public String getAsm() { - return asm; - } - - @Override - public String toString() { - return asm ; - } - } - - @Override - public String toString() { - StringBuffer out = new StringBuffer(); - for (AsmStatement asmStatement : sequence) { - out.append(asmStatement+"\n"); - } - return out.toString(); - } -} diff --git a/src/dk/camelot64/kickc/icl/NumberParser.java b/src/dk/camelot64/kickc/icl/NumberParser.java index 35fba88c6..d3d577180 100644 --- a/src/dk/camelot64/kickc/icl/NumberParser.java +++ b/src/dk/camelot64/kickc/icl/NumberParser.java @@ -19,7 +19,7 @@ public class NumberParser { return parseDecInt(literal); } } else { - throw new RuntimeException("Not Implemented: non-integer parsing"); + throw new NumberFormatException("Not Implemented: non-integer parsing. "+literal); } } diff --git a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java index 7c341099c..cc8184b7f 100644 --- a/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java +++ b/src/dk/camelot64/kickc/icl/Pass4CodeGeneration.java @@ -1,7 +1,6 @@ package dk.camelot64.kickc.icl; -import dk.camelot64.kickc.asm.AsmFragment; -import dk.camelot64.kickc.asm.AsmSequence; +import dk.camelot64.kickc.asm.*; import java.util.List; @@ -18,13 +17,13 @@ public class Pass4CodeGeneration { this.symbols = symbols; } - public AsmSequence generate() { - AsmSequence asm = new AsmSequence(); + public AsmProgram generate() { + AsmProgram asm = new AsmProgram(); for (ControlFlowBlock block : graph.getAllBlocks()) { // Generate entry points (if needed) genBlockEntryPoints(asm, block); // Generate label - genAsmLabel(asm, block.getLabel()); + asm.addLabel(block.getLabel().getName().replace('@', 'B')); // Generate statements genStatements(asm, block); // Generate exit @@ -33,13 +32,13 @@ public class Pass4CodeGeneration { if(defaultSuccessor.getStatements().size()>0 && defaultSuccessor.getStatements().get(0) instanceof StatementPhi) { genBlockPhiTransition(asm, block, defaultSuccessor); } - genAsmJump(asm, defaultSuccessor.getLabel().getName()); + asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getName().replace('@', 'B')); } } return asm; } - private void genStatements(AsmSequence asm, ControlFlowBlock block) { + private void genStatements(AsmProgram asm, ControlFlowBlock block) { for (Statement statement : block.getStatements()) { if (!(statement instanceof StatementPhi)) { genStatement(asm, statement); @@ -47,34 +46,34 @@ public class Pass4CodeGeneration { } } - private void genStatement(AsmSequence asm, Statement statement) { + private void genStatement(AsmProgram asm, Statement statement) { if (statement instanceof StatementAssignment) { AsmFragment asmFragment = new AsmFragment((StatementAssignment) statement, symbols); - asm.addAsm(" // " + statement + " // " + asmFragment.getSignature()); - asmFragment.generateAsm(asm); + asm.addComment(statement + " // " + asmFragment.getSignature()); + asmFragment.generate(asm); } else if (statement instanceof StatementConditionalJump) { AsmFragment asmFragment = new AsmFragment((StatementConditionalJump) statement, symbols); - asm.addAsm(" // " + statement + " // " + asmFragment.getSignature()); - asmFragment.generateAsm(asm); + asm.addComment(statement + " // " + asmFragment.getSignature()); + asmFragment.generate(asm); } else { throw new RuntimeException("Statement not supported "+statement); } } - private void genBlockEntryPoints(AsmSequence asm, ControlFlowBlock block) { + private void genBlockEntryPoints(AsmProgram asm, ControlFlowBlock block) { List statements = block.getStatements(); if (statements.size() > 0 && (statements.get(0) instanceof StatementPhi)) { for (ControlFlowBlock predecessor : block.getPredecessors()) { if(block.equals(predecessor.getConditionalSuccessor())) { genBlockPhiTransition(asm, predecessor, block); - genAsmJump(asm, block.getLabel().getName()); + asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getName().replace('@', 'B')); } } } } - private void genBlockPhiTransition(AsmSequence asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) { - genAsmLabel(asm, toBlock.getLabel().getName() + "_from_" + fromBlock.getLabel().getName()); + private void genBlockPhiTransition(AsmProgram asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) { + asm.addLabel((toBlock.getLabel().getName() + "_from_" + fromBlock.getLabel().getName()).replace('@', 'B')); for (Statement statement : toBlock.getStatements()) { if (!(statement instanceof StatementPhi)) { // No more phi statements to handle @@ -98,27 +97,15 @@ public class Pass4CodeGeneration { } } - private void genAsmMove(AsmSequence asm, LValue lValue, RValue rValue) { + private void genAsmMove(AsmProgram asm, LValue lValue, RValue rValue) { if(getRegister(lValue).equals(getRegister(rValue))) { // Do not move from register to itself - asm.addAsm(" // " + lValue + " = " + rValue + " // register copy " ); + asm.addComment(lValue + " = " + rValue + " // register copy " ); return; } AsmFragment asmFragment = new AsmFragment(lValue, rValue, symbols); - asm.addAsm(" // " + lValue + " = " + rValue + " // " + asmFragment.getSignature()); - asmFragment.generateAsm(asm); - } - - private void genAsmLabel(AsmSequence asm, Label label) { - genAsmLabel(asm, label.getName()); - } - - private void genAsmLabel(AsmSequence asm, String label) { - asm.addAsm(label.replace('@', 'B') + ":"); - } - - private void genAsmJump(AsmSequence asm, String label) { - asm.addAsm(" jmp " + label.replace('@', 'B')); + asm.addComment(lValue + " = " + rValue + " // " + asmFragment.getSignature()); + asmFragment.generate(asm); } diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index ea302c408..ca5ca6842 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.test; +import dk.camelot64.kickc.asm.AsmProgram; 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; @@ -64,14 +64,14 @@ public class Main { Pass4CodeGeneration pass4CodeGeneration = new Pass4CodeGeneration(controlFlowGraph, symbolTable); - AsmSequence asmSequence = pass4CodeGeneration.generate(); + AsmProgram asmProgram = pass4CodeGeneration.generate(); System.out.println("SYMBOLS"); System.out.println(symbolTable.toString()); System.out.println("CONTROL FLOW GRAPH"); System.out.println(controlFlowGraph.toString()); System.out.println("ASSEMBLER"); - System.out.println(asmSequence.toString()); + System.out.println(asmProgram.toString()); } }