1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-06-03 07:29:37 +00:00

Retired old ASM sequence for new ASM program

This commit is contained in:
jespergravgaard 2017-05-21 10:56:26 +02:00
parent 651f02e153
commit 0ba8ac742e
10 changed files with 97 additions and 111 deletions

View File

@ -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;

View File

@ -32,4 +32,5 @@ public class AsmComment implements AsmLine {
public String getAsm() {
return "// "+comment;
}
}

View File

@ -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);
}

View File

@ -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<AsmInstructionType> 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;
}
}

View File

@ -31,6 +31,6 @@ public class AsmLabel implements AsmLine {
@Override
public String getAsm() {
return ":"+label;
return label+":";
}
}

View File

@ -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();
}
}

View File

@ -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<AsmStatement> sequence;
public AsmSequence() {
this.sequence = new ArrayList<>();
}
public List<AsmStatement> 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();
}
}

View File

@ -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);
}
}

View File

@ -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<Statement> 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);
}

View File

@ -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());
}
}