mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-29 18:49:42 +00:00
Refactored calling distance.
This commit is contained in:
parent
eb69af8fe7
commit
8c7a144579
@ -46,22 +46,21 @@ final public class AsmFragmentInstanceSpecBuilder {
|
|||||||
/**
|
/**
|
||||||
* Create a fragment instance spec factory for a banked call
|
* Create a fragment instance spec factory for a banked call
|
||||||
*
|
*
|
||||||
* @param callingConvention The calling convention
|
* @param toProcedure The procedure being called
|
||||||
* @param proximity The calling distance of the call
|
* @param callingDistance 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 program The program
|
* @param program The program
|
||||||
* @return the fragment instance spec factory
|
* @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);
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(
|
AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(
|
||||||
callingConvention.getShortName(),
|
toProcedure.getCallingConvention().getShortName(),
|
||||||
proximity.toString(),
|
callingDistance.toString(),
|
||||||
(proximity.equals(Procedure.CallingProximity.NEAR)?null:toBank.bankArea()));
|
(callingDistance.equals(Procedure.CallingDistance.NEAR)?null:toBank.bankArea()));
|
||||||
ScopeRef codeScope = program.getScope().getRef();
|
ScopeRef codeScope = program.getScope().getRef();
|
||||||
bindings.bind("c1", new ConstantInteger(toBank.bankNumber()));
|
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);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,19 +77,19 @@ public interface AsmFragmentSignature {
|
|||||||
|
|
||||||
final private String callingConvention;
|
final private String callingConvention;
|
||||||
|
|
||||||
final private String proximity;
|
final private String callingDistance;
|
||||||
|
|
||||||
final private String toBankArea;
|
final private String toBankArea;
|
||||||
|
|
||||||
public CallBanked(String callingConvention, String proximity, String toBankArea) {
|
public CallBanked(String callingConvention, String callingDistance, String toBankArea) {
|
||||||
this.callingConvention = callingConvention;
|
this.callingConvention = callingConvention;
|
||||||
this.proximity = proximity;
|
this.callingDistance = callingDistance;
|
||||||
this.toBankArea = toBankArea;
|
this.toBankArea = toBankArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "call_" + callingConvention + "_" + proximity + ((toBankArea==null)?"":("_"+toBankArea));
|
return "call_" + callingConvention + "_" + callingDistance + ((toBankArea==null)?"":("_"+toBankArea));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ public class Procedure extends Scope {
|
|||||||
private List<Comment> comments;
|
private List<Comment> comments;
|
||||||
/** Reserved zeropage addresses. */
|
/** Reserved zeropage addresses. */
|
||||||
private List<Integer> reservedZps;
|
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;
|
private String segmentCode;
|
||||||
/** The list of constructor procedures for this procedure. The constructor procedures are called during program initialization. */
|
/** The list of constructor procedures for this procedure. The constructor procedures are called during program initialization. */
|
||||||
private final List<ProcedureRef> constructorRefs;
|
private final List<ProcedureRef> constructorRefs;
|
||||||
@ -43,7 +43,7 @@ public class Procedure extends Scope {
|
|||||||
private StatementSource definitionSource;
|
private StatementSource definitionSource;
|
||||||
/**
|
/**
|
||||||
* The bank that the procedure code is placed in.
|
* 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.
|
* If null, the procedure is in a common bank (always visible) and all calls will be near.
|
||||||
*/
|
*/
|
||||||
private Bank bank;
|
private Bank bank;
|
||||||
@ -65,17 +65,16 @@ public class Procedure extends Scope {
|
|||||||
this.bank = bank;
|
this.bank = bank;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The different distances between banked code, which will determine the type of call needed. */
|
/** The bank distance between a caller and callee, which will determine the type of call needed. */
|
||||||
public enum CallingProximity {
|
public enum CallingDistance {
|
||||||
/** No bank change is needed. Caller and callee are both in the same bank or in the common bank. */
|
/** Caller and callee are both in the same bank or in the common bank. No bank change is needed. */
|
||||||
NEAR,
|
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,
|
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;
|
FAR;
|
||||||
|
|
||||||
|
public static CallingDistance forCall(Bank from, Bank to) {
|
||||||
public static CallingProximity forCall(Bank from, Bank to) {
|
|
||||||
if(to==null) {
|
if(to==null) {
|
||||||
// NEAR: call to the common bank
|
// NEAR: call to the common bank
|
||||||
return NEAR;
|
return NEAR;
|
||||||
|
@ -901,15 +901,15 @@ public class Pass4CodeGeneration {
|
|||||||
genBlockPhiTransition(asm, block, callSuccessor, block.getScope());
|
genBlockPhiTransition(asm, block, callSuccessor, block.getScope());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Procedure.CallingProximity callingProximity = Procedure.CallingProximity.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||||
if(Procedure.CallingProximity.NEAR.equals(callingProximity)) {
|
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
|
||||||
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||||
} else {
|
} 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())) {
|
} else if (Procedure.CallingConvention.STACK_CALL.equals(toProcedure.getCallingConvention())) {
|
||||||
final Procedure.CallingProximity callingProximity = Procedure.CallingProximity.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||||
if(Procedure.CallingProximity.NEAR.equals(callingProximity)) {
|
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
|
||||||
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
|
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
|
||||||
@ -922,8 +922,8 @@ public class Pass4CodeGeneration {
|
|||||||
ProgramScope scope = getScope();
|
ProgramScope scope = getScope();
|
||||||
Procedure toProcedure = scope.getProcedure(procedureRef);
|
Procedure toProcedure = scope.getProcedure(procedureRef);
|
||||||
Procedure fromProcedure = block.getProcedure(this.program);
|
Procedure fromProcedure = block.getProcedure(this.program);
|
||||||
final Procedure.CallingProximity callingProximity = Procedure.CallingProximity.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||||
if(Procedure.CallingProximity.NEAR.equals(callingProximity)) {
|
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
|
||||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
|
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
|
||||||
} else {
|
} else {
|
||||||
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
|
throw new CompileError("Stack Call procedure not supported in banked mode " + toProcedure.toString(program));
|
||||||
|
Loading…
Reference in New Issue
Block a user