mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-14 09:30:57 +00:00
Merge commit 'db49ca6aabe96f0ca9ec355f33a4fadf33324f93' into far-call-isolated
This commit is contained in:
commit
19b8de78a4
@ -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' ;
|
||||
|
@ -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
|
||||
|
@ -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}
|
@ -0,0 +1,4 @@
|
||||
jsr $FFE6
|
||||
.byte <{la1}
|
||||
.byte >{la1}
|
||||
.byte {c1}
|
@ -0,0 +1,4 @@
|
||||
jsr $FFE6
|
||||
.byte <{la1}
|
||||
.byte >{la1}
|
||||
.byte {c1}
|
@ -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);
|
||||
}
|
||||
|
@ -71,11 +71,12 @@ public interface AsmFragmentSignature {
|
||||
}
|
||||
|
||||
/**
|
||||
* ASM fragment signature for a far jsr <code>if(A) goto B</code>.
|
||||
* ASM fragment signature for a banked jsr <code>if(A) goto B</code>.
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
25
src/main/java/dk/camelot64/kickc/model/Bank.java
Normal file
25
src/main/java/dk/camelot64/kickc/model/Bank.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<String, KickCParser.PragmaContext> pragmaCodeSegs;
|
||||
|
||||
public Program() {
|
||||
|
@ -28,8 +28,6 @@ public class StatementCall extends StatementBase implements StatementLValue, Sta
|
||||
private List<RValue> 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<RValue> parameters, StatementSource source, List<Comment> 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();
|
||||
}
|
||||
|
@ -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<Comment> comments) {
|
||||
super(source, comments);
|
||||
this.procedureType = procedureType;
|
||||
this.procedure = procedure;
|
||||
this.callingConvention = callingConvention;
|
||||
this.bankFar = bankFar;
|
||||
}
|
||||
|
||||
public SymbolTypeProcedure getProcedureType() {
|
||||
|
@ -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) &&
|
||||
|
@ -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<String, Symbol> symbols;
|
||||
|
@ -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.
|
||||
|
@ -295,20 +295,13 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
case CParser.PRAGMA_DATA_SEG:
|
||||
this.currentDataSegment = pragmaParamName(pragmaParamSingle(ctx));
|
||||
break;
|
||||
case CParser.PRAGMA_FAR:
|
||||
case CParser.PRAGMA_BANK:
|
||||
try {
|
||||
final int size = ctx.getChildCount();
|
||||
if(size==7) {
|
||||
final String pragmaFarSegment = pragmaParamFarSegment(ctx.pragmaParam(0));
|
||||
final Number pragmaFarBank = pragmaParamNumber(ctx.pragmaParam(1));
|
||||
if (size > 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<Objec
|
||||
throw new CompileError("Illegal parameter " + ctx.getText(), new StatementSource(ctx));
|
||||
}
|
||||
break;
|
||||
case CParser.PRAGMA_NEAR:
|
||||
this.currentFarSegment = null; // When the current far segment is null, any function that is far will be called as far.
|
||||
case CParser.PRAGMA_NOBANK:
|
||||
this.currentBank = null; // When the current far segment is null, any function that is far will be called as far.
|
||||
break;
|
||||
case CParser.PRAGMA_RESOURCE:
|
||||
String resourceFileName = pragmaParamString(pragmaParamSingle(ctx));
|
||||
@ -393,21 +386,22 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the FAR parameter of a #pragma
|
||||
* If the parameter is not a FAR the compiler will fail out
|
||||
* Parse the BANK AREA parameter of a #pragma
|
||||
* If the parameter is not a BANK AREA the compiler will fail out
|
||||
*
|
||||
* @param paramCtx The parameter to parse
|
||||
* @return The name
|
||||
*/
|
||||
private String pragmaParamFarSegment(KickCParser.PragmaParamContext paramCtx) {
|
||||
private String pragmaParamBankArea(KickCParser.PragmaParamContext paramCtx) {
|
||||
if(!(paramCtx instanceof KickCParser.PragmaParamNameContext))
|
||||
throw new CompileError("Expected a FAR parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
final String pragmaFarSegment = ((KickCParser.PragmaParamNameContext) paramCtx).NAME().getText();
|
||||
if(this.program.getPragmaCodeSegs().get(pragmaFarSegment) != null) {
|
||||
return pragmaFarSegment;
|
||||
} else {
|
||||
throw new CompileError("Expected a previously declared CODE_SEG parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
}
|
||||
throw new CompileError("Expected a BANK AREA parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
final String pragmaBankArea = ((KickCParser.PragmaParamNameContext) paramCtx).NAME().getText();
|
||||
// if(this.program.getPragmaCodeSegs().get(pragmaBankArea) != null) {
|
||||
// return pragmaBankArea;
|
||||
// } else {
|
||||
// throw new CompileError("Expected a previously declared CODE_SEG parameter. Found '" + paramCtx.getText() + "'.", new StatementSource(paramCtx.getParent()));
|
||||
// }
|
||||
return pragmaBankArea;
|
||||
}
|
||||
|
||||
|
||||
@ -480,7 +474,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
private String currentDataSegment = Scope.SEGMENT_DATA_DEFAULT;
|
||||
|
||||
/** The current far segment. */
|
||||
private FarSegment currentFarSegment;
|
||||
private Bank currentBank;
|
||||
|
||||
/** The current default interrupt type. */
|
||||
private String currentInterruptType;
|
||||
@ -537,7 +531,7 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
*/
|
||||
private Procedure declareProcedure(boolean defineProcedure, ParserRuleContext ctx, StatementSource statementSource) {
|
||||
|
||||
Procedure procedure = new Procedure(varDecl.getVarName(), (SymbolTypeProcedure) varDecl.getEffectiveType(), program.getScope(), currentCodeSegment, currentDataSegment, currentCallingConvention, currentFarSegment);
|
||||
Procedure procedure = new Procedure(varDecl.getVarName(), (SymbolTypeProcedure) varDecl.getEffectiveType(), program.getScope(), currentCodeSegment, currentDataSegment, currentCallingConvention, currentBank);
|
||||
addDirectives(procedure, varDecl.getDeclDirectives(), statementSource);
|
||||
// Check if the declaration matches any existing declaration!
|
||||
final Symbol existingSymbol = program.getScope().getSymbol(procedure.getRef());
|
||||
@ -1216,9 +1210,9 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
if(directive instanceof Directive.Inline) {
|
||||
procedure.setDeclaredInline(true);
|
||||
procedure.setCallingConvention(Procedure.CallingConvention.PHI_CALL);
|
||||
} else if(directive instanceof Directive.Far) {
|
||||
FarSegment farSegment = new FarSegment(((Directive.Far) directive).getFarSegmentName(), ((Directive.Far) directive).getFarSegmentBank(), ((Directive.Far) directive).getFarProcedurePrepare(), ((Directive.Far) directive).getFarProcedureExecute(), ((Directive.Far) directive).getFarProcedureFinalize());
|
||||
procedure.setFarSegment(farSegment);
|
||||
} else if(directive instanceof Directive.Bank) {
|
||||
Bank bank = new Bank(((Directive.Bank) directive).getBankArea(), ((Directive.Bank) directive).getBank());
|
||||
procedure.setBankLocation(bank);
|
||||
} else if(directive instanceof Directive.CallingConvention) {
|
||||
procedure.setCallingConvention(((Directive.CallingConvention) directive).callingConvention);
|
||||
} else if(directive instanceof Directive.Interrupt) {
|
||||
@ -1263,32 +1257,20 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor<Objec
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDirectiveFar(KickCParser.DirectiveFarContext ctx) {
|
||||
String farSegmentName = "";
|
||||
Long farSegmentBank = 0L;
|
||||
String farProcedurePrepare = null;
|
||||
String farProcedureExecute = null;
|
||||
String farProcedureFinalize = null;
|
||||
if(this.currentFarSegment != null) {
|
||||
farSegmentName = this.currentFarSegment.getFarSegment();
|
||||
farSegmentBank = this.currentFarSegment.getFarBank();
|
||||
farProcedurePrepare = this.currentFarSegment.getProcedurePrepare();
|
||||
farProcedureExecute = this.currentFarSegment.getProcedureExecute();
|
||||
farProcedureFinalize = this.currentFarSegment.getProcedureFinalize();
|
||||
public Object visitDirectiveBank(KickCParser.DirectiveBankContext ctx) {
|
||||
String bankArea = "";
|
||||
Long bank = -1L;
|
||||
if(this.currentBank != null) {
|
||||
bankArea = this.currentBank.getBankArea();
|
||||
bank = this.currentBank.getBank();
|
||||
}
|
||||
|
||||
if(ctx.getChildCount() >= 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
|
||||
|
@ -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<ControlFlowBlock> allBlocks = getGraph().getAllBlocks();
|
||||
ListIterator<ControlFlowBlock> blocksIt = allBlocks.listIterator();
|
||||
while(blocksIt.hasNext()) {
|
||||
ControlFlowBlock block = blocksIt.next();
|
||||
List<Statement> blockStatements = block.getStatements();
|
||||
ListIterator<Statement> 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<Statement> statementsIt, ControlFlowBlock block, ListIterator<ControlFlowBlock> 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));
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
14
src/test/kc/procedure-callingconvention-phi-bank-3.c
Normal file
14
src/test/kc/procedure-callingconvention-phi-bank-3.c
Normal file
@ -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;
|
||||
}
|
@ -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);
|
@ -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.
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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) {
|
@ -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;
|
||||
}
|
@ -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 {
|
Loading…
x
Reference in New Issue
Block a user