diff --git a/src/main/antlr4/dk/camelot64/kickc/parser/KickCLexer.g4 b/src/main/antlr4/dk/camelot64/kickc/parser/KickCLexer.g4 index f784b250e..98ef7914a 100644 --- a/src/main/antlr4/dk/camelot64/kickc/parser/KickCLexer.g4 +++ b/src/main/antlr4/dk/camelot64/kickc/parser/KickCLexer.g4 @@ -75,8 +75,7 @@ LOCAL_RESERVE: '__zp_reserve' ; ADDRESS: '__address' ; ADDRESS_ZEROPAGE: '__zp' ; ADDRESS_MAINMEM: '__mem' ; -FAR: '__far' ; -NEAR: '__near' ; +BANK: '__bank' ; FORM_SSA: '__ssa' ; FORM_MA: '__ma' ; INTRINSIC: '__intrinsic' ; diff --git a/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 b/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 index 070ecaee8..50b509cdf 100644 --- a/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 +++ b/src/main/antlr4/dk/camelot64/kickc/parser/KickCParser.g4 @@ -162,7 +162,7 @@ directive | EXTERN #directiveExtern | EXPORT #directiveExport | INLINE #directiveInline - | FAR PAR_BEGIN NAME COMMA NUMBER (COMMA NAME COMMA NAME COMMA NAME)? PAR_END #directiveFar + | BANK PAR_BEGIN NAME COMMA NUMBER (COMMA NAME COMMA NAME COMMA NAME)? PAR_END #directiveBank | INTRINSIC #directiveIntrinsic | INTERRUPT ( PAR_BEGIN NAME PAR_END )? #directiveInterrupt | LOCAL_RESERVE PAR_BEGIN pragmaParam ( COMMA pragmaParam )* PAR_END #directiveReserveZp diff --git a/src/main/fragment/mos6502-common/call_far_cx16_execute.asm b/src/main/fragment/mos6502-common/call_far_cx16_execute.asm deleted file mode 100644 index 661d162d6..000000000 --- a/src/main/fragment/mos6502-common/call_far_cx16_execute.asm +++ /dev/null @@ -1,4 +0,0 @@ -jsr $FF6E // https://github.com/commanderx16/x16-docs/blob/master/X16%20Reference%20-%2004%20-%20KERNAL.md#function-name-jsrfar -.byte <{la1} -.byte >{la1} -.byte {c1} diff --git a/src/main/fragment/mos6502-common/call_far_cx16_ram_execute.asm b/src/main/fragment/mos6502-common/call_far_cx16_ram_execute.asm new file mode 100644 index 000000000..d316eb072 --- /dev/null +++ b/src/main/fragment/mos6502-common/call_far_cx16_ram_execute.asm @@ -0,0 +1,4 @@ +jsr $FFE6 +.byte <{la1} +.byte >{la1} +.byte {c1} diff --git a/src/main/fragment/mos6502-common/call_far_cx16_finalize.asm b/src/main/fragment/mos6502-common/call_far_cx16_ram_finalize.asm similarity index 100% rename from src/main/fragment/mos6502-common/call_far_cx16_finalize.asm rename to src/main/fragment/mos6502-common/call_far_cx16_ram_finalize.asm diff --git a/src/main/fragment/mos6502-common/call_far_cx16_prepare.asm b/src/main/fragment/mos6502-common/call_far_cx16_ram_prepare.asm similarity index 100% rename from src/main/fragment/mos6502-common/call_far_cx16_prepare.asm rename to src/main/fragment/mos6502-common/call_far_cx16_ram_prepare.asm diff --git a/src/main/fragment/mos6502-common/call_far_cx16_rom_execute.asm b/src/main/fragment/mos6502-common/call_far_cx16_rom_execute.asm new file mode 100644 index 000000000..d316eb072 --- /dev/null +++ b/src/main/fragment/mos6502-common/call_far_cx16_rom_execute.asm @@ -0,0 +1,4 @@ +jsr $FFE6 +.byte <{la1} +.byte >{la1} +.byte {c1} diff --git a/src/main/fragment/mos6502-common/call_far_cx16_rom_finalize.asm b/src/main/fragment/mos6502-common/call_far_cx16_rom_finalize.asm new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/fragment/mos6502-common/call_far_cx16_rom_prepare.asm b/src/main/fragment/mos6502-common/call_far_cx16_rom_prepare.asm new file mode 100644 index 000000000..e69de29bb diff --git a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java index c39c919d9..859f55804 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java +++ b/src/main/java/dk/camelot64/kickc/fragment/AsmFragmentInstanceSpecBuilder.java @@ -42,54 +42,55 @@ final public class AsmFragmentInstanceSpecBuilder { } /** - * Create a fragment instance spec factory for a far call prepare + * Create a fragment instance spec factory for a bank call prepare * - * @param bankFar The bank where the procedure is to be called. + * @param bankArea The bank area where the procedure is to be called. + * @param bank The bank where the procedure is to be called. * @param procedureName The full name of the procedure. * @param program The program * @return the fragment instance spec factory */ - public static AsmFragmentInstanceSpec farCallPrepare(Long bankFar, String procedureName, Program program) { + public static AsmFragmentInstanceSpec bankCallPrepare(String bankArea, Long bank, String procedureName, Program program) { AsmFragmentBindings bindings = new AsmFragmentBindings(program); - AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(bankFar, program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.PrepareExecuteFinalize.Prepare); + AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(bankArea, bank, program.getTargetPlatform().getName(), AsmFragmentSignature.CallBanked.PrepareExecuteFinalize.Prepare); ScopeRef codeScope = program.getScope().getRef(); -// ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope(); - bindings.bind("c1", new ConstantInteger(bankFar)); + bindings.bind("c1", new ConstantInteger(bank)); bindings.bind("la1", new LabelRef(procedureName)); return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } /** - * Create a fragment instance spec factory for a far call execute + * Create a fragment instance spec factory for a bank call execute * - * @param bankFar The bank where the procedure is to be called. + * @param bankArea The bank area where the procedure is to be called. + * @param bank The bank where the procedure is to be called. * @param procedureName The full name of the procedure. * @param program The program * @return the fragment instance spec factory */ - public static AsmFragmentInstanceSpec farCallExecute(Long bankFar, String procedureName, Program program) { + public static AsmFragmentInstanceSpec bankCallExecute(String bankArea, Long bank, String procedureName, Program program) { AsmFragmentBindings bindings = new AsmFragmentBindings(program); - AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(bankFar, program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.PrepareExecuteFinalize.Execute); + AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(bankArea, bank, program.getTargetPlatform().getName(), AsmFragmentSignature.CallBanked.PrepareExecuteFinalize.Execute); ScopeRef codeScope = program.getScope().getRef(); -// ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope(); - bindings.bind("c1", new ConstantInteger(bankFar)); + bindings.bind("c1", new ConstantInteger(bank)); bindings.bind("la1", new LabelRef(procedureName)); return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } /** - * Create a fragment instance spec factory for a far call finalize + * Create a fragment instance spec factory for a bank call finalize * - * @param bankFar The bank where the procedure is to be called. + * @param bankArea The bank area where the procedure is to be called. + * @param bank The bank where the procedure is to be called. * @param procedureName The full name of the procedure. * @param program The program * @return the fragment instance spec factory */ - public static AsmFragmentInstanceSpec farCallFinalize(Long bankFar, String procedureName, Program program) { + public static AsmFragmentInstanceSpec bankCallFinalize(String bankArea, Long bank, String procedureName, Program program) { AsmFragmentBindings bindings = new AsmFragmentBindings(program); - AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(bankFar, program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.PrepareExecuteFinalize.Finalize); + AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(bankArea, bank, program.getTargetPlatform().getName(), AsmFragmentSignature.CallBanked.PrepareExecuteFinalize.Finalize); ScopeRef codeScope = program.getScope().getRef(); - bindings.bind("c1", new ConstantInteger(bankFar)); + bindings.bind("c1", new ConstantInteger(bank)); bindings.bind("la1", new LabelRef(procedureName)); return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope); } diff --git a/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java b/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java index 45a2689e7..456864880 100644 --- a/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java +++ b/src/main/java/dk/camelot64/kickc/fragment/signature/AsmFragmentSignature.java @@ -71,11 +71,12 @@ public interface AsmFragmentSignature { } /** - * ASM fragment signature for a far jsr if(A) goto B. + * ASM fragment signature for a banked jsr if(A) goto B. */ - class CallFar implements AsmFragmentSignature { + class CallBanked implements AsmFragmentSignature { - final private Long bankFar; + final private String bankArea; + final private Long bank; final private String targetPlatform; public enum PrepareExecuteFinalize { @@ -84,18 +85,19 @@ public interface AsmFragmentSignature { Finalize } - final private PrepareExecuteFinalize far; + final private PrepareExecuteFinalize fragment; - public CallFar(Long bankFar, String targetPlatform, PrepareExecuteFinalize far) { - this.bankFar = bankFar; + public CallBanked(String bankArea, Long bank, String targetPlatform, PrepareExecuteFinalize fragment) { + this.bankArea = bankArea; + this.bank = bank; this.targetPlatform = targetPlatform; - this.far = far; + this.fragment = fragment; } @Override public String getName() { - return "call_far" + "_" + targetPlatform + "_" + far.name().toLowerCase(); + return "call_far" + "_" + targetPlatform.toLowerCase() + "_" + bankArea.toLowerCase() + "_" + fragment.name().toLowerCase(); } } diff --git a/src/main/java/dk/camelot64/kickc/model/Bank.java b/src/main/java/dk/camelot64/kickc/model/Bank.java new file mode 100644 index 000000000..99220e7f4 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/model/Bank.java @@ -0,0 +1,25 @@ +package dk.camelot64.kickc.model; + +/** A Bank segment. */ +public class Bank { + + private final String bankArea; + private Long bank; + + public Bank(String bankArea, Long bank) { + this.bankArea = bankArea; + this.bank = bank; + } + + public String getBankArea() { + return bankArea; + } + + public Long getBank() { + return bank; + } + + public void setBank(Long bank) { + this.bank = bank; + } +} diff --git a/src/main/java/dk/camelot64/kickc/model/Directive.java b/src/main/java/dk/camelot64/kickc/model/Directive.java index e155d5587..fe4728cb7 100644 --- a/src/main/java/dk/camelot64/kickc/model/Directive.java +++ b/src/main/java/dk/camelot64/kickc/model/Directive.java @@ -43,43 +43,24 @@ public class Directive { public Inline() { super("inline"); } } - /** Function declared far. */ - static public class Far extends Directive { + /** Function declared banked. */ + static public class Bank extends Directive { - private String farSegmentName; - private Long farSegmentBank; - private String farProcedurePrepare; - private String farProcedureExecute; - private String farProcedureFinalize; + private String bankArea; + private Long bank; - - public Far(String farSegmentName, Long farSegmentBank, String farProcedurePrepare, String farProcedureExecute, String farProcedureFinalize) { - super("far" ); - this.farSegmentName = farSegmentName; - this.farSegmentBank = farSegmentBank; - this.farProcedurePrepare = farProcedurePrepare; - this.farProcedureExecute = farProcedureExecute; - this.farProcedureFinalize = farProcedureFinalize; + public Bank(String bankArea, Long bank) { + super("bank" ); + this.bankArea = bankArea; + this.bank = bank; } - public String getFarSegmentName() { - return farSegmentName; + public String getBankArea() { + return bankArea; } - public Long getFarSegmentBank() { - return farSegmentBank; - } - - public String getFarProcedurePrepare() { - return farProcedurePrepare; - } - - public String getFarProcedureExecute() { - return farProcedureExecute; - } - - public String getFarProcedureFinalize() { - return farProcedureFinalize; + public Long getBank() { + return bank; } } diff --git a/src/main/java/dk/camelot64/kickc/model/FarSegment.java b/src/main/java/dk/camelot64/kickc/model/FarSegment.java deleted file mode 100644 index 18f8dd976..000000000 --- a/src/main/java/dk/camelot64/kickc/model/FarSegment.java +++ /dev/null @@ -1,43 +0,0 @@ -package dk.camelot64.kickc.model; - -/** A far segment. */ -public class FarSegment { - - private final String farSegment; - private Long farBank; - private final String procedurePrepare; - private final String procedureExecute; - private final String procedureFinalize; - - public FarSegment(String name, Long bank, String procedurePrepare, String procedureExecute, String procedureFinalize) { - this.farSegment = name; - this.farBank = bank; - this.procedurePrepare = procedurePrepare; - this.procedureExecute = procedureExecute; - this.procedureFinalize = procedureFinalize; - } - - public String getFarSegment() { - return farSegment; - } - - public Long getFarBank() { - return farBank; - } - - public void setFarBank(Long farBank) { - this.farBank = farBank; - } - - public String getProcedurePrepare() { - return procedurePrepare; - } - - public String getProcedureExecute() { - return procedureExecute; - } - - public String getProcedureFinalize() { - return procedureFinalize; - } -} diff --git a/src/main/java/dk/camelot64/kickc/model/Program.java b/src/main/java/dk/camelot64/kickc/model/Program.java index 898c50028..000cad6bd 100644 --- a/src/main/java/dk/camelot64/kickc/model/Program.java +++ b/src/main/java/dk/camelot64/kickc/model/Program.java @@ -105,7 +105,7 @@ public class Program { private NaturalLoopSet loopSet; /** The register weight of all variables describing how much the variable would theoretically gain from being in a register. PASS 3-5 (CACHED ON-DEMAND) */ private VariableRegisterWeights variableRegisterWeights; - /** All #pragma code segments. Collected during parsing. These are used by the far() pragmas to validate if the code segment exists during compilation.*/ + /** All #pragma code segments. Collected during parsing. These are used by the bank() pragmas to validate if the code segment exists during compilation.*/ private final Map pragmaCodeSegs; public Program() { diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java index 5c941f835..db5563d05 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCall.java @@ -28,8 +28,6 @@ public class StatementCall extends StatementBase implements StatementLValue, Sta private List parameters; /** This is the initial assignment of the lValue. */ private boolean initialAssignment; - /** This contains the far call parameters */ - private Long bankFar; public StatementCall(LValue lValue, String procedureName, List parameters, StatementSource source, List comments) { super(source, comments); @@ -66,12 +64,6 @@ public class StatementCall extends StatementBase implements StatementLValue, Sta this.parameters = parameters; } - public void setBankFar(Long bankFar) { - this.bankFar = bankFar; - } - - public Long getBankFar() { return this.bankFar; } - public int getNumParameters() { return parameters.size(); } diff --git a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java index 620491ecb..f1f54fe05 100644 --- a/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java +++ b/src/main/java/dk/camelot64/kickc/model/statements/StatementCallExecute.java @@ -28,15 +28,11 @@ public class StatementCallExecute extends StatementBase implements StatementCall /** The calling convention to use. */ private Procedure.CallingConvention callingConvention; - /** This contains the far call parameters */ - private Long bankFar; - public StatementCallExecute(SymbolTypeProcedure procedureType, RValue procedure, Procedure.CallingConvention callingConvention, StatementSource source, List comments) { super(source, comments); this.procedureType = procedureType; this.procedure = procedure; this.callingConvention = callingConvention; - this.bankFar = bankFar; } public SymbolTypeProcedure getProcedureType() { diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java b/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java index c1b761e7f..49f9854fa 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java @@ -1,7 +1,7 @@ package dk.camelot64.kickc.model.symbols; import dk.camelot64.kickc.model.Comment; -import dk.camelot64.kickc.model.FarSegment; +import dk.camelot64.kickc.model.Bank; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.statements.StatementSource; import dk.camelot64.kickc.model.types.SymbolType; @@ -26,8 +26,6 @@ public class Procedure extends Scope { private boolean variableLengthParameterList; /** true if the procedure is declared inline. */ private boolean declaredInline; - /** true if the procedure is declared far. */ - private boolean declaredFar; /** True if the procedure is declared intrinsic. */ private boolean declaredIntrinsic; /** The type of interrupt that the procedure serves. Null for all procedures not serving an interrupt. */ @@ -44,8 +42,8 @@ public class Procedure extends Scope { private boolean isConstructor; /** The source of the procedure definition. */ private StatementSource definitionSource; - /** The far segment information. Collected during parsing. These are used to compare with the current currentFarSegment to decide a near or a far call, and to keep inline calling routines.*/ - private FarSegment farSegment; + /** The bank segment information. Collected during parsing. These are used to compare with the current currentBank to decide a near or a far call, and to keep inline calling routines.*/ + private Bank bankLocation; /** The names of all legal intrinsic procedures. */ @@ -56,12 +54,12 @@ public class Procedure extends Scope { Pass1ByteXIntrinsicRewrite.INTRINSIC_MAKELONG4 ); - public FarSegment getFarSegment() { - return farSegment; + public Bank getBankLocation() { + return bankLocation; } - public void setFarSegment(FarSegment farSegment) { - this.farSegment = farSegment; + public void setBankLocation(Bank bankLocation) { + this.bankLocation = bankLocation; } @@ -100,11 +98,11 @@ public class Procedure extends Scope { /** The calling convention used for this procedure. */ private CallingConvention callingConvention; - public Procedure(String name, SymbolTypeProcedure procedureType, Scope parentScope, String codeSegment, String dataSegment, CallingConvention callingConvention, FarSegment farSegment) { + public Procedure(String name, SymbolTypeProcedure procedureType, Scope parentScope, String codeSegment, String dataSegment, CallingConvention callingConvention, Bank bankLocation) { super(name, parentScope, dataSegment); this.procedureType = procedureType; this.declaredInline = false; - this.farSegment = farSegment; + this.bankLocation = bankLocation; this.interruptType = null; this.comments = new ArrayList<>(); this.codeSegment = codeSegment; @@ -214,17 +212,24 @@ public class Procedure extends Scope { this.declaredInline = declaredInline; } - public boolean isDeclaredFar() { - return farSegment != null; + public boolean isDeclaredBanked() { + return bankLocation != null; } - public Long getFarBank() { - if(farSegment!=null) - return farSegment.getFarBank(); + public Long getBank() { + if(bankLocation != null) + return bankLocation.getBank(); else return 0L; } + public String getBankArea() { + if(bankLocation != null) + return bankLocation.getBankArea(); + else + return ""; + } + public String getInterruptType() { return interruptType; } @@ -285,8 +290,8 @@ public class Procedure extends Scope { if(declaredIntrinsic) { res.append("__intrinsic "); } - if(declaredFar) { - res.append("__far(").append("bank").append(") "); + if(isDeclaredBanked()) { + res.append("__bank(").append("bank").append(") "); } if(!callingConvention.equals(CallingConvention.PHI_CALL)) { res.append(getCallingConvention().getName()).append(" "); @@ -326,7 +331,7 @@ public class Procedure extends Scope { Procedure procedure = (Procedure) o; return variableLengthParameterList == procedure.variableLengthParameterList && declaredInline == procedure.declaredInline && - declaredFar == procedure.declaredFar && + isDeclaredBanked() == procedure.isDeclaredBanked() && declaredIntrinsic == procedure.declaredIntrinsic && isConstructor == procedure.isConstructor && Objects.equals(procedureType, procedure.procedureType) && diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java index 89541598a..77ecbb068 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Scope.java @@ -16,8 +16,8 @@ public abstract class Scope implements Symbol { public static final String SEGMENT_CODE_DEFAULT = "Code"; /** The default data segment. */ public static final String SEGMENT_DATA_DEFAULT = "Data"; - /** The default far segment. */ - public static final String SEGMENT_FAR_DEFAULT = ""; + /** The default bank segment. */ + public static final Long SEGMENT_BANK_DEFAULT = -1L; private String name; private HashMap symbols; diff --git a/src/main/java/dk/camelot64/kickc/parser/CParser.java b/src/main/java/dk/camelot64/kickc/parser/CParser.java index 806287556..029c6d5f6 100644 --- a/src/main/java/dk/camelot64/kickc/parser/CParser.java +++ b/src/main/java/dk/camelot64/kickc/parser/CParser.java @@ -107,13 +107,13 @@ public class CParser { */ public static final String PRAGMA_RESOURCE = "resource"; /** - * #pragma far(...) specifies the scope of the sequent functions to be far. Segments are defined in the linker file. + * #pragma bank(...) specifies the scope of the sequent functions to be located in a bank using a specific banking area. */ - public static final String PRAGMA_FAR = "far"; + public static final String PRAGMA_BANK = "bank"; /** - * #pragma near specifies the scope of the sequent functions to be near. Segments are defined in the linker file. + * #pragma nobank specifies the scope of the sequent functions to be near. Segments are defined in the linker file. */ - public static final String PRAGMA_NEAR = "near"; + public static final String PRAGMA_NOBANK = "nobank"; /** * The Program. diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 00cde33d7..b6cf3dae6 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -295,20 +295,13 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor 7) { - final String call_prepare = pragmaParamName(ctx.pragmaParam(2)); - final String call_execute = pragmaParamName(ctx.pragmaParam(3)); - final String call_finalize = pragmaParamName(ctx.pragmaParam(4)); - this.currentFarSegment = new FarSegment(pragmaFarSegment, pragmaFarBank.longValue(), call_prepare, call_execute, call_finalize); - } else { - this.currentFarSegment = new FarSegment(pragmaFarSegment, pragmaFarBank.longValue(), "", "", ""); - } + final String pragmaBankArea = pragmaParamBankArea(ctx.pragmaParam(0)); + final Number pragmaBank = pragmaParamNumber(ctx.pragmaParam(1)); + this.currentBank = new Bank(pragmaBankArea, pragmaBank.longValue()); } else { throw new CompileError("Expected at least 2 pragma parameters. Found '" + ctx.getText() + "'.", new StatementSource(ctx)); } @@ -316,8 +309,8 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor= 5) { - farSegmentName = ctx.getChild(2).getText(); - farSegmentBank = Long.valueOf(ctx.getChild(4).getText()); + bankArea = ctx.getChild(2).getText(); + bank = Long.valueOf(ctx.getChild(4).getText()); } - if(ctx.getChildCount() == 11) { - farProcedurePrepare = ctx.getChild(6).getText(); - farProcedureExecute = ctx.getChild(8).getText(); - farProcedureFinalize = ctx.getChild(10).getText(); - } - - return new Directive.Far(farSegmentName, farSegmentBank, farProcedurePrepare, farProcedureExecute, farProcedureFinalize); + return new Directive.Bank(bankArea, bank); } @Override diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureFar.java b/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureFar.java deleted file mode 100644 index 60d3e3fae..000000000 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1ProcedureFar.java +++ /dev/null @@ -1,71 +0,0 @@ -package dk.camelot64.kickc.passes; - -import dk.camelot64.kickc.model.InternalError; -import dk.camelot64.kickc.model.*; -import dk.camelot64.kickc.model.iterator.ProgramValue; -import dk.camelot64.kickc.model.iterator.ProgramValueHandler; -import dk.camelot64.kickc.model.iterator.ProgramValueIterator; -import dk.camelot64.kickc.model.statements.*; -import dk.camelot64.kickc.model.symbols.*; -import dk.camelot64.kickc.model.types.SymbolType; -import dk.camelot64.kickc.model.values.*; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.ListIterator; - -/** Pass that modifies a control flow graph to far call any procedures declared as far */ -public class Pass1ProcedureFar extends Pass1Base { - - public Pass1ProcedureFar(Program program) { - super(program); - } - - @Override - public boolean step() { - List allBlocks = getGraph().getAllBlocks(); - ListIterator blocksIt = allBlocks.listIterator(); - while(blocksIt.hasNext()) { - ControlFlowBlock block = blocksIt.next(); - List blockStatements = block.getStatements(); - ListIterator statementsIt = blockStatements.listIterator(); - while(statementsIt.hasNext()) { - Statement statement = statementsIt.next(); - if(statement instanceof StatementCall) { - StatementCall call = (StatementCall) statement; - ProcedureRef procedureRef = call.getProcedure(); - Procedure procedure = getScope().getProcedure(procedureRef); - if(procedure.isDeclaredFar()) { - if(procedure.getInterruptType()!=null) { - throw new CompileError("Error! Interrupts cannot be far called. "+procedure.getRef().toString()); - } - farProcedureCall(call, procedure, statementsIt, block, blocksIt); - // Continue -// return true; - } - } - } - } - return false; - } - - /** - * Inline a specific call to a procedure. - * - * @param call The call to the far procedure - * @param procedure The procedure being called - * @param statementsIt The statement iterator pointing to the call statement - * @param block The block containing the call - * @param blocksIt The block iterator pointing to the block containing the call - */ - private void farProcedureCall(StatementCall call, Procedure procedure, ListIterator statementsIt, ControlFlowBlock block, ListIterator blocksIt) { - Scope callScope = getScope().getScope(block.getScope()); - // Here we add to the call the properties to build a far call depending on the platform. - // The all properties have been entered in the __far() directive in the source code. - // These properties are then used in pass4 of the compiler, to build the platform dependent fragment to execute the far call. - -// call.setBankFar(procedure.getBankFar()); - getLog().append("Far call " + call.toString(getProgram(), false)); - } -} diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 6fc625f7d..0d3568c70 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -867,36 +867,26 @@ public class Pass4CodeGeneration { } } // Note: I've chosen to keep this code duplication between phi and stack calling convention, for later maintenance flexibility, if any. - // We check if the procedure is declared as far, and if the calling procedure is not in the same bank as the procedure called. - if(procedure.isDeclaredFar() && procedureFrom.getFarBank() != procedure.getFarBank()) { + // We check if the procedure is declared as banked, and if the calling procedure is not in the same bank as the procedure called. + if(procedure.isDeclaredBanked() && procedureFrom.getBank() != procedure.getBank()) { // In this case, Generate ASM for a far call. // The call is constructed in a prepare, execute and finalize compiler .asm fragments respectively. - // The bank and other preparations are set in the far_call_[platform]_prepare.asm fragment. - // The actual jsr statement is embedded in the far_call_[platform]_execute.asm fragment. - // After the jsr, finalization of the call is defined in the far_call_[platform]_finalize.asm fragment. - // TODO: rework to prepare, execute, finalize - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallPrepare(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExecute(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallFinalize(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); -// asm.addInstruction("jsr far", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false); + // The bank and other preparations are set in the call_far_[platform]_[bankarea]_prepare.asm fragment. + // The actual jsr statement is embedded in the far_call_[platform]_[bankarea]_execute.asm fragment. + // After the jsr, finalization of the call is defined in the far_call_[platform]_[bankarea]_finalize.asm fragment. + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallPrepare(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallExecute(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallFinalize(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); } else { // Otherwise, Generate AM for a normal near call. - // In case of a far call, we assume the bank does not need to be changed. asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false); } } else if (Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) { - // Note: I've chosen to keep this code duplication between phi and stack calling convention, for later maintenance flexibility, if any. - // We check if the procedure is declared as far, and if the calling procedure is not in the same bank as the procedure called. - if(procedure.isDeclaredFar() && procedure.getFarBank() != procedureFrom.getFarBank()) { - // In this case, Generate ASM for a far call. - // The call is constructed in a prepare, execute and finalize compiler .asm fragments respectively. - // The bank and other preparations are set in the far_call_[platform]_prepare.asm fragment. - // The actual jsr statement is embedded in the far_call_[platform]_execute.asm fragment. - // After the jsr, finalization of the call is defined in the far_call_[platform]_finalize.asm fragment. - // TODO: rework to prepare, execute, finalize - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallPrepare(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExecute(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallFinalize(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); + // Same as PHI + if(procedure.isDeclaredBanked() && procedure.getBank() != procedureFrom.getBank()) { + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallPrepare(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallExecute(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallFinalize(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); } else { asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false); } @@ -907,11 +897,11 @@ public class Pass4CodeGeneration { Procedure procedure = getScope().getProcedure(call.getProcedure()); Procedure procedureFrom = block.getProcedure(this.program); // We obtain from where the procedure is called, to validate the bank equality. RValue procedureRVal = call.getProcedureRVal(); - // Generate ASM for a call - if(procedure.isDeclaredFar() && procedureFrom.getFarBank() != procedure.getFarBank()) { - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallPrepare(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExecute(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); - AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallFinalize(procedure.getFarSegment().getFarBank(), call.getProcedure().getFullName(), program), program); + // Same as PHI + if(procedure.isDeclaredBanked() && procedureFrom.getBank() != procedure.getBank()) { + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallPrepare(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallExecute(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); + AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.bankCallFinalize(procedure.getBankArea(), procedure.getBank(), call.getProcedure().getFullName(), program), program); } else { AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program); } diff --git a/src/test/kc/procedure-callingconvention-phi-far-0.c b/src/test/kc/procedure-callingconvention-phi-bank-0.c similarity index 80% rename from src/test/kc/procedure-callingconvention-phi-far-0.c rename to src/test/kc/procedure-callingconvention-phi-bank-0.c index ca53104b6..54243fc55 100644 --- a/src/test/kc/procedure-callingconvention-phi-far-0.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-0.c @@ -7,6 +7,6 @@ void main(void) { } #pragma code_seg(stage) -char __far(stage,2) plus(char a, char b) { +char __bank(ram,2) plus(char a, char b) { return a+b; } diff --git a/src/test/kc/procedure-callingconvention-phi-far-1.c b/src/test/kc/procedure-callingconvention-phi-bank-1.c similarity index 54% rename from src/test/kc/procedure-callingconvention-phi-far-1.c rename to src/test/kc/procedure-callingconvention-phi-bank-1.c index 5a3bd5633..585ab0f82 100644 --- a/src/test/kc/procedure-callingconvention-phi-far-1.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-1.c @@ -7,24 +7,8 @@ void main(void) { } #pragma code_seg(stage) -#pragma far(stage, 1) +#pragma bank(ram, 1) char plus(char a, char b) { return a+b; } - -void stage_entry() { - asm { - lda 0 - pha - lda #1 - sta 0 - } -} - -void stage_exit() { - asm { - pla - sta 0 - } -} diff --git a/src/test/kc/procedure-callingconvention-phi-far-3.c b/src/test/kc/procedure-callingconvention-phi-bank-2.c similarity index 55% rename from src/test/kc/procedure-callingconvention-phi-far-3.c rename to src/test/kc/procedure-callingconvention-phi-bank-2.c index 18a600d0f..e56b218aa 100644 --- a/src/test/kc/procedure-callingconvention-phi-far-3.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-2.c @@ -7,24 +7,9 @@ void main(void) { } #pragma code_seg(stage) -#pragma far(stage) +#pragma bank(rubbish, 1) char plus(char a, char b) { return a+b; } -void stage_entry() { - asm { - lda 0 - pha - lda #1 - sta 0 - } -} - -void stage_exit() { - asm { - pla - sta 0 - } -} diff --git a/src/test/kc/procedure-callingconvention-phi-bank-3.c b/src/test/kc/procedure-callingconvention-phi-bank-3.c new file mode 100644 index 000000000..655f28876 --- /dev/null +++ b/src/test/kc/procedure-callingconvention-phi-bank-3.c @@ -0,0 +1,14 @@ +// Test a far call procedure with a calling convention sp + +char* const SCREEN = (char*)0x0400; + +void main(void) { + SCREEN[0] = plus('0', 7); +} + +#pragma code_seg(stage) +#pragma bank(stage, 2) + +char plus(char a, char b) { + return a+b; +} diff --git a/src/test/kc/procedure-callingconvention-phi-far-4.c b/src/test/kc/procedure-callingconvention-phi-bank-4.c similarity index 85% rename from src/test/kc/procedure-callingconvention-phi-far-4.c rename to src/test/kc/procedure-callingconvention-phi-bank-4.c index b186b8bb1..0459fcaa0 100644 --- a/src/test/kc/procedure-callingconvention-phi-far-4.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-4.c @@ -3,13 +3,13 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(stage) -#pragma far(stage, 20) +#pragma bank(stage, 20) char plus(char a, char b) { return a+b; } -#pragma near +#pragma nobank void main(void) { SCREEN[0] = plus('0', 7); diff --git a/src/test/kc/procedure-callingconvention-phi-far-5.c b/src/test/kc/procedure-callingconvention-phi-bank-5.c similarity index 92% rename from src/test/kc/procedure-callingconvention-phi-far-5.c rename to src/test/kc/procedure-callingconvention-phi-bank-5.c index 7949bb569..9e8021010 100644 --- a/src/test/kc/procedure-callingconvention-phi-far-5.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-5.c @@ -3,7 +3,7 @@ char* const SCREEN = (char*)0x0400; #pragma code_seg(bank_1) -#pragma far(bank_1, 1) +#pragma bank(ram, 1) char func_bank1_a(char a, char b) { return a+b; @@ -20,7 +20,7 @@ char func_bank1_d(char a, char b) { } #pragma code_seg(bank_2) -#pragma far(bank_2, 2) +#pragma bank(ram, 2) char func_bank2_a(char a, char b) { return a+b; @@ -47,17 +47,17 @@ char func_bank2_f(char a, char b) { return func_bank1_b(a,b); } -#pragma near +#pragma nobank -char __far(bank_1, 1) func_bank1_b(char a, char b) { +char __bank(ram, 1) func_bank1_b(char a, char b) { return a+b; } -char __far(bank_2, 2) func_bank2_b(char a, char b) { +char __bank(ram, 2) func_bank2_b(char a, char b) { return a+b; } -#pragma near +#pragma nobank char func_bank1_e(char a, char b) { // this should be a far call, because the call is to bank 1. diff --git a/src/test/kc/procedure-callingconvention-phi-far-2.c b/src/test/kc/procedure-callingconvention-phi-far-2.c deleted file mode 100644 index 4fedebf68..000000000 --- a/src/test/kc/procedure-callingconvention-phi-far-2.c +++ /dev/null @@ -1,30 +0,0 @@ -// Test a far call procedure with a calling convention sp - -char* const SCREEN = (char*)0x0400; - -void main(void) { - SCREEN[0] = plus('0', 7); -} - -#pragma code_seg(stage) -#pragma far(rubbish, 1, stage_prepare, stage_execution, stage_exit) - -char plus(char a, char b) { - return a+b; -} - -void stage_entry() { - asm { - lda 0 - pha - lda #1 - sta 0 - } -} - -void stage_exit() { - asm { - pla - sta 0 - } -} diff --git a/src/test/kc/procedure-callingconvention-stack-far-0.c b/src/test/kc/procedure-callingconvention-stack-bank-0.c similarity index 76% rename from src/test/kc/procedure-callingconvention-stack-far-0.c rename to src/test/kc/procedure-callingconvention-stack-bank-0.c index b232fde4f..3801b0673 100644 --- a/src/test/kc/procedure-callingconvention-stack-far-0.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-0.c @@ -7,6 +7,6 @@ void main(void) { } #pragma code_seg(test) -char __far(test, 2) __stackcall plus(char a, char b) { +char __bank(ram, 2) __stackcall plus(char a, char b) { return a+b; } \ No newline at end of file diff --git a/src/test/kc/procedure-callingconvention-stack-far-1.c b/src/test/kc/procedure-callingconvention-stack-bank-1.c similarity index 82% rename from src/test/kc/procedure-callingconvention-stack-far-1.c rename to src/test/kc/procedure-callingconvention-stack-bank-1.c index 458e13cd4..da246a882 100644 --- a/src/test/kc/procedure-callingconvention-stack-far-1.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-1.c @@ -9,6 +9,6 @@ void main(void) { #pragma calling(__stackcall) #pragma code_seg(test) -char __far(test,20) plus(char a, char b) { +char __bank(ram,20) plus(char a, char b) { return a+b; } \ No newline at end of file diff --git a/src/test/kc/procedure-callingconvention-stack-far-2.c b/src/test/kc/procedure-callingconvention-stack-bank-2.c similarity index 86% rename from src/test/kc/procedure-callingconvention-stack-far-2.c rename to src/test/kc/procedure-callingconvention-stack-bank-2.c index 328dd4d34..cb8a3bc86 100644 --- a/src/test/kc/procedure-callingconvention-stack-far-2.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-2.c @@ -14,7 +14,7 @@ void main(void) { } // this should give a pragma error during compile, as test is not declared yet. -char __far(test, 20) __stackcall plus(char a, char b) { +char __bank(ram, 20) __stackcall plus(char a, char b) { i++; return a+b; } \ No newline at end of file diff --git a/src/test/kc/procedure-callingconvention-stack-far-3.c b/src/test/kc/procedure-callingconvention-stack-bank-3.c similarity index 80% rename from src/test/kc/procedure-callingconvention-stack-far-3.c rename to src/test/kc/procedure-callingconvention-stack-bank-3.c index 1bfec448f..6ab8d136f 100644 --- a/src/test/kc/procedure-callingconvention-stack-far-3.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-3.c @@ -20,23 +20,23 @@ void main(void) { #pragma code_seg(test3) #pragma code_seg(Code) -void __far(test, 20) pval() { +void __bank(ram, 20) pval() { printval(); } -void __far(test2, 21) ival() { +void __bank(ram, 21) ival() { incval(); } -void __far(test, 20) printval() { +void __bank(ram, 20) printval() { SCREEN[0] = val; } -void __far(test2, 21) incval() { +void __bank(ram, 21) incval() { val++; } -#pragma near +#pragma nobank void printother() { for(char i:0..5) { diff --git a/src/test/kc/procedure-callingconvention-stack-far-4.c b/src/test/kc/procedure-callingconvention-stack-bank-4.c similarity index 84% rename from src/test/kc/procedure-callingconvention-stack-far-4.c rename to src/test/kc/procedure-callingconvention-stack-bank-4.c index c006ecd6f..76c66aa26 100644 --- a/src/test/kc/procedure-callingconvention-stack-far-4.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-4.c @@ -19,12 +19,12 @@ void main(void) { } } -struct Point __far(1) get(char i) { +struct Point __bank(ram,1) get(char i) { struct Point p = { i, i/2 }; return p; } -void __far(2) print(struct Point p) { +void __bank(ram,2) print(struct Point p) { SCREEN[idx++] = p.x; SCREEN[idx++] = p.y; } diff --git a/src/test/kc/procedure-callingconvention-stack-far-5.c b/src/test/kc/procedure-callingconvention-stack-bank-5.c similarity index 84% rename from src/test/kc/procedure-callingconvention-stack-far-5.c rename to src/test/kc/procedure-callingconvention-stack-bank-5.c index 925beedec..3bfac0ef3 100644 --- a/src/test/kc/procedure-callingconvention-stack-far-5.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-5.c @@ -7,7 +7,7 @@ void main(void) { *SCREEN = pow2(6); } -char __stackcall __far(1) pow2(char n) { +char __stackcall __bank(ram,1) pow2(char n) { if (n == 0) return 1; else {