Refactored calling distance.

This commit is contained in:
jespergravgaard 2023-04-23 21:07:16 +02:00
parent eb69af8fe7
commit 8c7a144579
4 changed files with 27 additions and 29 deletions

View File

@ -46,22 +46,21 @@ final public class AsmFragmentInstanceSpecBuilder {
/**
* Create a fragment instance spec factory for a banked call
*
* @param callingConvention The calling convention
* @param proximity The calling distance of the call
* @param toBank The bank of the procedure being called
* @param procedureName The full name of the procedure being called.
* @param toProcedure The procedure being called
* @param callingDistance The calling distance of the call
* @param program The program
* @return the fragment instance spec factory
*/
public static AsmFragmentInstanceSpec callBanked(Procedure.CallingConvention callingConvention, Procedure.CallingProximity proximity, Bank toBank, String procedureName, Program program) {
public static AsmFragmentInstanceSpec callBanked(Procedure toProcedure, Procedure.CallingDistance callingDistance, Program program) {
final Bank toBank = toProcedure.getBank();
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(
callingConvention.getShortName(),
proximity.toString(),
(proximity.equals(Procedure.CallingProximity.NEAR)?null:toBank.bankArea()));
toProcedure.getCallingConvention().getShortName(),
callingDistance.toString(),
(callingDistance.equals(Procedure.CallingDistance.NEAR)?null:toBank.bankArea()));
ScopeRef codeScope = program.getScope().getRef();
bindings.bind("c1", new ConstantInteger(toBank.bankNumber()));
bindings.bind("la1", new LabelRef(procedureName));
bindings.bind("la1", new LabelRef(toProcedure.getFullName()));
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
}

View File

@ -77,19 +77,19 @@ public interface AsmFragmentSignature {
final private String callingConvention;
final private String proximity;
final private String callingDistance;
final private String toBankArea;
public CallBanked(String callingConvention, String proximity, String toBankArea) {
public CallBanked(String callingConvention, String callingDistance, String toBankArea) {
this.callingConvention = callingConvention;
this.proximity = proximity;
this.callingDistance = callingDistance;
this.toBankArea = toBankArea;
}
@Override
public String getName() {
return "call_" + callingConvention + "_" + proximity + ((toBankArea==null)?"":("_"+toBankArea));
return "call_" + callingConvention + "_" + callingDistance + ((toBankArea==null)?"":("_"+toBankArea));
}
}

View File

@ -33,7 +33,7 @@ public class Procedure extends Scope {
private List<Comment> comments;
/** Reserved zeropage addresses. */
private List<Integer> reservedZps;
/** The data and code segment to put the procedure into. When null the procedure is not assigned to the code segment. */
/** The code segment to put the procedure code into. When null the procedure is not assigned to the code segment. */
private String segmentCode;
/** The list of constructor procedures for this procedure. The constructor procedures are called during program initialization. */
private final List<ProcedureRef> constructorRefs;
@ -43,7 +43,7 @@ public class Procedure extends Scope {
private StatementSource definitionSource;
/**
* The bank that the procedure code is placed in.
* Used to decide whether to produce near, close or far call when generating code.
* Used to decide whether to produce near, close or far call code when generating calls.
* If null, the procedure is in a common bank (always visible) and all calls will be near.
*/
private Bank bank;
@ -65,17 +65,16 @@ public class Procedure extends Scope {
this.bank = bank;
}
/** The different distances between banked code, which will determine the type of call needed. */
public enum CallingProximity {
/** No bank change is needed. Caller and callee are both in the same bank or in the common bank. */
/** The bank distance between a caller and callee, which will determine the type of call needed. */
public enum CallingDistance {
/** Caller and callee are both in the same bank or in the common bank. No bank change is needed. */
NEAR,
/** A direct bank change is needed. Caller is in the common bank or a different banking area. */
/** Caller is in the common bank or a different banking area. A direct bank change is needed. */
CLOSE,
/** A trampoline bank change is needed. Caller and callee are different banks of the same banking area. */
/** Caller and callee are different banks of the same banking area. A trampoline bank change is needed. */
FAR;
public static CallingProximity forCall(Bank from, Bank to) {
public static CallingDistance forCall(Bank from, Bank to) {
if(to==null) {
// NEAR: call to the common bank
return NEAR;

View File

@ -901,15 +901,15 @@ public class Pass4CodeGeneration {
genBlockPhiTransition(asm, block, callSuccessor, block.getScope());
}
}
final Procedure.CallingProximity callingProximity = Procedure.CallingProximity.forCall(fromProcedure.getBank(), toProcedure.getBank());
if(Procedure.CallingProximity.NEAR.equals(callingProximity)) {
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
} else {
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.callBanked(Procedure.CallingConvention.PHI_CALL, callingProximity, toProcedure.getBank(), call.getProcedure().getFullName(), program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.callBanked(toProcedure, callingDistance, program), program);
}
} else if (Procedure.CallingConvention.STACK_CALL.equals(toProcedure.getCallingConvention())) {
final Procedure.CallingProximity callingProximity = Procedure.CallingProximity.forCall(fromProcedure.getBank(), toProcedure.getBank());
if(Procedure.CallingProximity.NEAR.equals(callingProximity)) {
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
} else {
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
@ -922,8 +922,8 @@ public class Pass4CodeGeneration {
ProgramScope scope = getScope();
Procedure toProcedure = scope.getProcedure(procedureRef);
Procedure fromProcedure = block.getProcedure(this.program);
final Procedure.CallingProximity callingProximity = Procedure.CallingProximity.forCall(fromProcedure.getBank(), toProcedure.getBank());
if(Procedure.CallingProximity.NEAR.equals(callingProximity)) {
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
} else {
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));