mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-20 15:29:10 +00:00
Retired old ASM sequence for new ASM program
This commit is contained in:
parent
651f02e153
commit
0ba8ac742e
@ -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;
|
||||
|
@ -32,4 +32,5 @@ public class AsmComment implements AsmLine {
|
||||
public String getAsm() {
|
||||
return "// "+comment;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,6 @@ public class AsmLabel implements AsmLine {
|
||||
|
||||
@Override
|
||||
public String getAsm() {
|
||||
return ":"+label;
|
||||
return label+":";
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user