mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-10 13:38:18 +00:00
Moved calling distance to bank.
This commit is contained in:
parent
8b7afa4ad0
commit
606ea29132
@ -51,13 +51,13 @@ final public class AsmFragmentInstanceSpecBuilder {
|
||||
* @param program The program
|
||||
* @return the fragment instance spec factory
|
||||
*/
|
||||
public static AsmFragmentInstanceSpec callBanked(Procedure toProcedure, Procedure.CallingDistance callingDistance, Program program) {
|
||||
public static AsmFragmentInstanceSpec callBanked(Procedure toProcedure, Bank.CallingDistance callingDistance, Program program) {
|
||||
final Bank toBank = toProcedure.getBank();
|
||||
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||
AsmFragmentSignature signature = new AsmFragmentSignature.CallBanked(
|
||||
toProcedure.getCallingConvention().getShortName(),
|
||||
callingDistance.toString(),
|
||||
(callingDistance.equals(Procedure.CallingDistance.NEAR)?null:toBank.bankArea()));
|
||||
(callingDistance.equals(Bank.CallingDistance.NEAR)?null:toBank.bankArea()));
|
||||
ScopeRef codeScope = program.getScope().getRef();
|
||||
bindings.bind("c1", new ConstantInteger(toBank.bankNumber()));
|
||||
bindings.bind("la1", new LabelRef(toProcedure.getFullName()));
|
||||
|
@ -44,15 +44,12 @@ public class Directive {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Bank which collects the necessary data to handle banking.
|
||||
* For example, on the Commander X16, RAM is banked from address 0xA000 till 0xBFFF.
|
||||
* Zeropage 0x00 configures this banked RAM, with a number from 0x00 till 0xff.
|
||||
* So banked RAM is is a bankArea, and the bank is a configurable bank number in the bankArea.
|
||||
* Bank to place code into. Used for determining call distance.
|
||||
*/
|
||||
static public class Bank extends Directive {
|
||||
|
||||
private String bankArea; // A bank area is a memory range that is banked on a target platform.
|
||||
private Long bankNumber; // A bank is a number that defines a bank configuration in a bank area.
|
||||
private String bankArea;
|
||||
private Long bankNumber;
|
||||
|
||||
public Bank(String bankArea, Long bankNumber) {
|
||||
super("bank" );
|
||||
|
@ -135,4 +135,39 @@ public record Bank(String bankArea, Long bankNumber) {
|
||||
return "__bank(" + this.bankArea() + ", " + this.bankNumber() + ") ";
|
||||
}
|
||||
}
|
||||
|
||||
/** 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,
|
||||
/** Caller is in the common bank or a different banking area. A direct bank change is needed. */
|
||||
CLOSE,
|
||||
/** Caller and callee are different banks of the same banking area. A trampoline bank change is needed. */
|
||||
FAR;
|
||||
|
||||
public static CallingDistance forCall(Bank from, Bank to) {
|
||||
if(to.isCommon()) {
|
||||
// NEAR: call to the common bank
|
||||
return NEAR;
|
||||
} else if(to.equals(from)) {
|
||||
// NEAR: call to the same bank in the same banking area
|
||||
return NEAR;
|
||||
} else if(from.isCommon()) {
|
||||
// CLOSE: call from common bank to any bank
|
||||
return CLOSE;
|
||||
} else if(!from.bankArea().equals(to.bankArea())) {
|
||||
// CLOSE: from one banking area to another
|
||||
return CLOSE;
|
||||
} else {
|
||||
// FAR: banked to different bank in same bank area
|
||||
return FAR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -63,41 +63,6 @@ public class Procedure extends Scope {
|
||||
this.bank = Objects.requireNonNull(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,
|
||||
/** Caller is in the common bank or a different banking area. A direct bank change is needed. */
|
||||
CLOSE,
|
||||
/** Caller and callee are different banks of the same banking area. A trampoline bank change is needed. */
|
||||
FAR;
|
||||
|
||||
public static CallingDistance forCall(Bank from, Bank to) {
|
||||
if(to.isCommon()) {
|
||||
// NEAR: call to the common bank
|
||||
return NEAR;
|
||||
} else if(to.equals(from)) {
|
||||
// NEAR: call to the same bank in the same banking area
|
||||
return NEAR;
|
||||
} else if(from.isCommon()) {
|
||||
// CLOSE: call from common bank to any bank
|
||||
return CLOSE;
|
||||
} else if(!from.bankArea().equals(to.bankArea())) {
|
||||
// CLOSE: from one banking area to another
|
||||
return CLOSE;
|
||||
} else {
|
||||
// FAR: banked to different bank in same bank area
|
||||
return FAR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** The method for passing parameters and return value to the procedure. */
|
||||
public enum CallingConvention {
|
||||
/** Parameters and return value handled through PHI-transitions. */
|
||||
@ -355,11 +320,23 @@ public class Procedure extends Scope {
|
||||
if(o == null || getClass() != o.getClass()) return false;
|
||||
if(!super.equals(o)) return false;
|
||||
Procedure procedure = (Procedure) o;
|
||||
return variableLengthParameterList == procedure.variableLengthParameterList && declaredInline == procedure.declaredInline && declaredIntrinsic == procedure.declaredIntrinsic && isConstructor == procedure.isConstructor && Objects.equals(procedureType, procedure.procedureType) && Objects.equals(parameterNames, procedure.parameterNames) && Objects.equals(interruptType, procedure.interruptType) && Objects.equals(comments, procedure.comments) && Objects.equals(reservedZps, procedure.reservedZps) && Objects.equals(segmentCode, procedure.segmentCode) && Objects.equals(constructorRefs, procedure.constructorRefs) && Objects.equals(definitionSource, procedure.definitionSource) && Objects.equals(bank, procedure.bank) && callingConvention == procedure.callingConvention;
|
||||
return variableLengthParameterList == procedure.variableLengthParameterList &&
|
||||
declaredInline == procedure.declaredInline &&
|
||||
declaredIntrinsic == procedure.declaredIntrinsic &&
|
||||
isConstructor == procedure.isConstructor &&
|
||||
Objects.equals(procedureType, procedure.procedureType) &&
|
||||
Objects.equals(parameterNames, procedure.parameterNames) &&
|
||||
Objects.equals(interruptType, procedure.interruptType) &&
|
||||
Objects.equals(comments, procedure.comments) &&
|
||||
Objects.equals(reservedZps, procedure.reservedZps) &&
|
||||
Objects.equals(segmentCode, procedure.segmentCode) &&
|
||||
Objects.equals(constructorRefs, procedure.constructorRefs) &&
|
||||
Objects.equals(bank, procedure.bank) &&
|
||||
callingConvention == procedure.callingConvention;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), procedureType, parameterNames, variableLengthParameterList, declaredInline, declaredIntrinsic, interruptType, comments, reservedZps, segmentCode, constructorRefs, isConstructor, definitionSource, bank, callingConvention);
|
||||
return Objects.hash(super.hashCode(), procedureType, parameterNames, variableLengthParameterList, declaredInline, declaredIntrinsic, interruptType, comments, reservedZps, segmentCode, constructorRefs, isConstructor, bank, callingConvention);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ public class CParser {
|
||||
*/
|
||||
public static final String PRAGMA_BANK = "bank";
|
||||
/**
|
||||
* #pragma nobank Changes the current bank to the default/common bank.
|
||||
* #pragma nobank Changes the current bank to the default/common/shared bank.
|
||||
*/
|
||||
public static final String PRAGMA_NOBANK = "nobank";
|
||||
|
||||
|
@ -900,15 +900,15 @@ public class Pass4CodeGeneration {
|
||||
genBlockPhiTransition(asm, block, callSuccessor, block.getScope());
|
||||
}
|
||||
}
|
||||
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
|
||||
final Bank.CallingDistance callingDistance = Bank.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||
if(Bank.CallingDistance.NEAR.equals(callingDistance)) {
|
||||
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||
} else {
|
||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.callBanked(toProcedure, callingDistance, program), program);
|
||||
}
|
||||
} else if (Procedure.CallingConvention.STACK_CALL.equals(toProcedure.getCallingConvention())) {
|
||||
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
|
||||
final Bank.CallingDistance callingDistance = Bank.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||
if(Bank.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));
|
||||
@ -921,11 +921,11 @@ public class Pass4CodeGeneration {
|
||||
ProgramScope scope = getScope();
|
||||
Procedure toProcedure = scope.getProcedure(procedureRef);
|
||||
Procedure fromProcedure = block.getProcedure(this.program);
|
||||
final Procedure.CallingDistance callingDistance = Procedure.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||
if(Procedure.CallingDistance.NEAR.equals(callingDistance)) {
|
||||
final Bank.CallingDistance callingDistance = Bank.CallingDistance.forCall(fromProcedure.getBank(), toProcedure.getBank());
|
||||
if(Bank.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));
|
||||
throw new CompileError("Call procedure not supported in banked mode " + toProcedure.toString(program));
|
||||
}
|
||||
RValue procedureRVal = call.getProcedureRVal();
|
||||
if (!(procedureRVal instanceof ProcedureRef)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user