mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-08 13:25:12 +00:00
far calls for __stackcall calling convention functions.
This commit is contained in:
committed by
Flight_Control
parent
828e38a8b3
commit
4a4d6f72d0
@@ -278,7 +278,7 @@ public class Compiler {
|
|||||||
getLog().append(program.getGraph().toString(program));
|
getLog().append(program.getGraph().toString(program));
|
||||||
}
|
}
|
||||||
new Pass1ProcedureInline(program).execute();
|
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();
|
new PassNStatementIndices(program).step();
|
||||||
program.clearCallGraph();
|
program.clearCallGraph();
|
||||||
new Pass1AssertNoRecursion(program).execute();
|
new Pass1AssertNoRecursion(program).execute();
|
||||||
|
@@ -45,33 +45,35 @@ final public class AsmFragmentInstanceSpecBuilder {
|
|||||||
/**
|
/**
|
||||||
* Create a fragment instance spec factory for a far call entry
|
* Create a fragment instance spec factory for a far call entry
|
||||||
*
|
*
|
||||||
* @param call The statement call
|
* @param bankFar The bank where the procedure is to be called.
|
||||||
* @param program The program
|
* @param procedureName The full name of the procedure.
|
||||||
|
* @param program The program
|
||||||
* @return the fragment instance spec factory
|
* @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);
|
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.getScope().getRef();
|
||||||
// ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
|
// ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
|
||||||
bindings.bind("c1", new ConstantInteger(call.getBankFar()));
|
bindings.bind("c1", new ConstantInteger(bankFar));
|
||||||
bindings.bind("la1", new LabelRef(call.getProcedure().getFullName()));
|
bindings.bind("la1", new LabelRef(procedureName));
|
||||||
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a fragment instance spec factory for a far call exit
|
* 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
|
* @param program The program
|
||||||
* @return the fragment instance spec factory
|
* @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);
|
AsmFragmentBindings bindings = new AsmFragmentBindings(program);
|
||||||
AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(call.getBankFar(), program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.EntryExit.Exit);
|
AsmFragmentSignature signature = new AsmFragmentSignature.CallFar(bankFar, program.getTargetPlatform().getName(), AsmFragmentSignature.CallFar.EntryExit.Exit);
|
||||||
ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
|
ScopeRef codeScope = program.getScope().getRef();
|
||||||
bindings.bind("la1", new LabelRef(codeScope.getFullName()));
|
bindings.bind("c1", new ConstantInteger(bankFar));
|
||||||
bindings.bind("la2", new ConstantInteger(call.getBankFar()));
|
bindings.bind("la1", new LabelRef(procedureName));
|
||||||
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
return new AsmFragmentInstanceSpec(program, signature, bindings, codeScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -28,11 +28,15 @@ public class StatementCallExecute extends StatementBase implements StatementCall
|
|||||||
/** The calling convention to use. */
|
/** The calling convention to use. */
|
||||||
private Procedure.CallingConvention callingConvention;
|
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) {
|
public StatementCallExecute(SymbolTypeProcedure procedureType, RValue procedure, Procedure.CallingConvention callingConvention, StatementSource source, List<Comment> comments) {
|
||||||
super(source, comments);
|
super(source, comments);
|
||||||
this.procedureType = procedureType;
|
this.procedureType = procedureType;
|
||||||
this.procedure = procedure;
|
this.procedure = procedure;
|
||||||
this.callingConvention = callingConvention;
|
this.callingConvention = callingConvention;
|
||||||
|
this.bankFar = bankFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SymbolTypeProcedure getProcedureType() {
|
public SymbolTypeProcedure getProcedureType() {
|
||||||
|
@@ -867,8 +867,8 @@ public class Pass4CodeGeneration {
|
|||||||
}
|
}
|
||||||
if(procedure.isDeclaredFar()) {
|
if(procedure.isDeclaredFar()) {
|
||||||
// Generate ASM for a call (in a bank or other)
|
// Generate ASM for a call (in a bank or other)
|
||||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call, program), program);
|
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call.getBankFar(), call.getProcedure().getFullName(), program), program);
|
||||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call, program), program);
|
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call.getBankFar(), call.getProcedure().getFullName(), program), program);
|
||||||
// asm.addInstruction("jsr far", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
// asm.addInstruction("jsr far", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||||
} else {
|
} else {
|
||||||
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
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())) {
|
} else if (Procedure.CallingConvention.STACK_CALL.equals(procedure.getCallingConvention())) {
|
||||||
if(procedure.isDeclaredFar()) {
|
if(procedure.isDeclaredFar()) {
|
||||||
// Generate ASM for a far call (in a bank or other)
|
// Generate ASM for a far call (in a bank or other)
|
||||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call, program), program);
|
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallEntry(call.getBankFar(), call.getProcedure().getFullName(), program), program);
|
||||||
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call, program), program);
|
AsmFragmentCodeGenerator.generateAsm(asm, AsmFragmentInstanceSpecBuilder.farCallExit(call.getBankFar(), call.getProcedure().getFullName(), program), program);
|
||||||
} else {
|
} else {
|
||||||
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
asm.addInstruction("jsr", CpuAddressingMode.ABS, call.getProcedure().getFullName(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (statement instanceof StatementCallExecute) {
|
} else if (statement instanceof StatementCallExecute) {
|
||||||
StatementCallExecute call = (StatementCallExecute) statement;
|
StatementCallExecute call = (StatementCallExecute) statement;
|
||||||
|
Procedure procedure = getScope().getProcedure(call.getProcedure());
|
||||||
RValue procedureRVal = call.getProcedureRVal();
|
RValue procedureRVal = call.getProcedureRVal();
|
||||||
// Generate ASM for a call
|
// 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)) {
|
if (!(procedureRVal instanceof ProcedureRef)) {
|
||||||
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
|
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
al C:400 .SCREEN
|
||||||
|
al C:80b .upstartEnd
|
||||||
|
al C:80d .main
|
||||||
|
al C:819 .plus
|
||||||
|
al C:37 .return
|
13
src/test/kc/procedure-callingconvention-phi-far-1.c
Normal file
13
src/test/kc/procedure-callingconvention-phi-far-1.c
Normal 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;
|
||||||
|
}
|
Reference in New Issue
Block a user