1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-12-21 14:30:21 +00:00

far calls for __stackcall calling convention functions.

This commit is contained in:
Sven Van de Velde 2022-11-16 17:11:18 +01:00 committed by Flight_Control
parent 828e38a8b3
commit 4a4d6f72d0
6 changed files with 48 additions and 18 deletions

View File

@ -278,7 +278,7 @@ public class Compiler {
getLog().append(program.getGraph().toString(program));
}
new Pass1ProcedureInline(program).execute();
new Pass1ProcedureFar(program).execute(); // Implements far calls to procedures defined in a bank.
new Pass1ProcedureFar(program).execute(); // Implements far calls to procedures defined in a bank. See https://gitlab.com/Flight_Control/kickc/-/commits/far-call-isolated
new PassNStatementIndices(program).step();
program.clearCallGraph();
new Pass1AssertNoRecursion(program).execute();

View File

@ -45,33 +45,35 @@ final public class AsmFragmentInstanceSpecBuilder {
/**
* Create a fragment instance spec factory for a far call entry
*
* @param call The statement call
* @param program The program
* @param bankFar 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 farCallEntry(StatementCall call, Program program) {
public static AsmFragmentInstanceSpec farCallEntry(Long bankFar, String procedureName, Program program) {
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(call.getBankFar(), program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.EntryExit.Entry);
AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(bankFar, program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.EntryExit.Entry);
ScopeRef codeScope = program.getScope().getRef();
// ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
bindings.bind("c1", new ConstantInteger(call.getBankFar()));
bindings.bind("la1", new LabelRef(call.getProcedure().getFullName()));
bindings.bind("c1", new ConstantInteger(bankFar));
bindings.bind("la1", new LabelRef(procedureName));
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
}
/**
* Create a fragment instance spec factory for a far call exit
*
* @param call The statement call
* @param bankFar 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 farCallExit(StatementCall call, Program program) {
public static AsmFragmentInstanceSpec farCallExit(Long bankFar, String procedureName, Program program) {
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(call.getBankFar(), program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.EntryExit.Exit);
ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
bindings.bind("la1", new LabelRef(codeScope.getFullName()));
bindings.bind("la2", new ConstantInteger(call.getBankFar()));
AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(bankFar, program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.EntryExit.Exit);
ScopeRef codeScope = program.getScope().getRef();
bindings.bind("c1", new ConstantInteger(bankFar));
bindings.bind("la1", new LabelRef(procedureName));
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
}

View File

@ -28,11 +28,15 @@ 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() {

View File

@ -867,8 +867,8 @@ public class Pass4CodeGeneration {
}
if(procedure.isDeclaredFar()) {
// Generate ASM for a call (in a bank or other)
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call, program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call, program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call.getBankFar(), call.getProcedure().getFullName(), program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call.getBankFar(), call.getProcedure().getFullName(), program), program);
// asm.addInstruction("jsr far", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
} else {
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
@ -876,17 +876,23 @@ public class Pass4CodeGeneration {
} else if (Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
if(procedure.isDeclaredFar()) {
// Generate ASM for a far call (in a bank or other)
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call, program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call, program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call.getBankFar(), call.getProcedure().getFullName(), program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call.getBankFar(), call.getProcedure().getFullName(), program), program);
} else {
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
}
}
} else if (statement instanceof StatementCallExecute) {
StatementCallExecute call = (StatementCallExecute) statement;
Procedure procedure = getScope().getProcedure(call.getProcedure());
RValue procedureRVal = call.getProcedureRVal();
// Generate ASM for a call
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
if(procedure.isDeclaredFar()) {
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(procedure.getBankFar(), call.getProcedure().getFullName(), program), program);
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(procedure.getBankFar(), call.getProcedure().getFullName(), program), program);
} else {
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.call(call, indirectCallCount++, program), program);
}
if (!(procedureRVal instanceof ProcedureRef)) {
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
}

View File

@ -0,0 +1,5 @@
al C:400 .SCREEN
al C:80b .upstartEnd
al C:80d .main
al C:819 .plus
al C:37 .return

View File

@ -0,0 +1,13 @@
// Test a procedure with calling convention stack
char* const SCREEN = (char*)0x0400;
void main(void) {
SCREEN[0] = plus('0', 7);
}
#pragma calling(__stackcall)
char __far(1) plus(char a, char b) {
return a+b;
}