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 {