diff --git a/src/main/fragment/mos6502-common/_stackgetbyte_vbuc1=vbuaa.asm b/src/main/fragment/mos6502-common/_stackgetbyte_vbuc1=vbuaa.asm new file mode 100644 index 000000000..a950d1216 --- /dev/null +++ b/src/main/fragment/mos6502-common/_stackgetbyte_vbuc1=vbuaa.asm @@ -0,0 +1,2 @@ +tsx +sta STACK_BASE+{c1},x \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/_stackgetword_vbuc1=vwuz1.asm b/src/main/fragment/mos6502-common/_stackgetword_vbuc1=vwuz1.asm new file mode 100644 index 000000000..568ff503a --- /dev/null +++ b/src/main/fragment/mos6502-common/_stackgetword_vbuc1=vwuz1.asm @@ -0,0 +1,5 @@ +tsx +lda {z1} +sta STACK_BASE+{c1},x +lda {z1}+1 +sta STACK_BASE+{c1}+1,x diff --git a/src/main/java/dk/camelot64/kickc/model/values/ParamStackPull.java b/src/main/java/dk/camelot64/kickc/model/values/ParamStackPull.java index 0e99f0a5a..6d40f290a 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ParamStackPull.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ParamStackPull.java @@ -3,7 +3,7 @@ package dk.camelot64.kickc.model.values; import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.types.SymbolType; -/** A value puslled from the stack. */ +/** A value pulled from the stack. */ public class ParamStackPull implements RValue { /** The type of value being pushed. */ diff --git a/src/main/java/dk/camelot64/kickc/model/values/ParamStackValue.java b/src/main/java/dk/camelot64/kickc/model/values/ParamStackValue.java index 191989505..0a74ccdf3 100644 --- a/src/main/java/dk/camelot64/kickc/model/values/ParamStackValue.java +++ b/src/main/java/dk/camelot64/kickc/model/values/ParamStackValue.java @@ -4,24 +4,24 @@ import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.types.SymbolType; /** The value passed into a function for a specific parameter using the stack. */ -public class ParamStackValue implements RValue { +public class ParamStackValue implements LValue { /** The constant holding the stack offset of the parameter. */ - private ConstantRef stackOffset; + private ConstantValue stackOffset; /** The type of the value to fetch from the stack. */ private SymbolType valueType; - public ParamStackValue(ConstantRef stackOffset, SymbolType valueType) { + public ParamStackValue(ConstantValue stackOffset, SymbolType valueType) { this.stackOffset = stackOffset; this.valueType = valueType; } - public ConstantRef getStackOffset() { + public ConstantValue getStackOffset() { return stackOffset; } - public void setStackOffset(ConstantRef stackOffset) { + public void setStackOffset(ConstantValue stackOffset) { this.stackOffset = stackOffset; } @@ -35,7 +35,8 @@ public class ParamStackValue implements RValue { @Override public String toString(Program program) { - return "paramstack("+valueType.getTypeName()+","+stackOffset+")"; + return "paramstack("+valueType.getTypeName()+","+stackOffset.toString(program)+")"; } + } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index 1c42b3188..4f050ce53 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -801,18 +801,37 @@ public class Pass4CodeGeneration { } } else if(statement instanceof StatementReturn) { - Procedure.InterruptType interruptType = null; + Procedure procedure = null; ScopeRef scope = block.getScope(); if(!scope.equals(ScopeRef.ROOT)) { - Procedure procedure = getScope().getProcedure(scope.getFullName()); - if(procedure != null) { - interruptType = procedure.getInterruptType(); + procedure = getScope().getProcedure(scope.getFullName()); + } + + if(procedure!=null && Procedure.CallingConvension.STACK_CALL.equals(procedure.getCallingConvension())) { + StatementReturn returnStatement = (StatementReturn) statement; + if(returnStatement.getValue()!=null) { + // Store return value on stack + SymbolType returnType = procedure.getReturnType(); + + // Find parameter/return stack size + int parameterBytes = 0; + for(Variable parameter : procedure.getParameters()) { + parameterBytes += parameter.getType().getSizeBytes(); + } + int returnOffset = parameterBytes - returnType.getSizeBytes(); + // TODO: Put the return stack offset into a named constant (look at PassNCallingConventionStack) + ConstantValue returnValueStackOffset = new ConstantInteger((long)returnOffset, SymbolType.BYTE); + AsmFragmentInstanceSpecFactory asmFragmentInstanceSpecFactory = new AsmFragmentInstanceSpecFactory(new ParamStackValue(returnValueStackOffset, returnType), returnStatement.getValue(), program, block.getScope()); + asm.startChunk(block.getScope(), statement.getIndex(), statement.toString(program, verboseAliveInfo)); + ensureEncoding(asm, asmFragmentInstanceSpecFactory); + generateAsm(asm, asmFragmentInstanceSpecFactory.getAsmFragmentInstanceSpec()); } } - if(interruptType == null) { + + if(procedure==null || procedure.getInterruptType() == null) { asm.addInstruction("rts", AsmAddressingMode.NON, null, false); } else { - generateInterruptExit(asm, statement, interruptType); + generateInterruptExit(asm, statement, procedure.getInterruptType()); } } else if(statement instanceof StatementAsm) { StatementAsm statementAsm = (StatementAsm) statement; diff --git a/src/test/ref/procedure-callingconvention-stack-0.asm b/src/test/ref/procedure-callingconvention-stack-0.asm index b061638cc..3293ed5f3 100644 --- a/src/test/ref/procedure-callingconvention-stack-0.asm +++ b/src/test/ref/procedure-callingconvention-stack-0.asm @@ -27,5 +27,7 @@ plus: { lda STACK_BASE+OFFSET_STACK_B,x clc adc.z a + tsx + sta STACK_BASE+1,x rts } diff --git a/src/test/ref/procedure-callingconvention-stack-0.cfg b/src/test/ref/procedure-callingconvention-stack-0.cfg index 7d27d5cc1..37c87d1a7 100644 --- a/src/test/ref/procedure-callingconvention-stack-0.cfg +++ b/src/test/ref/procedure-callingconvention-stack-0.cfg @@ -22,8 +22,8 @@ main::@return: scope:[main] from main __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) - [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) + [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus diff --git a/src/test/ref/procedure-callingconvention-stack-0.log b/src/test/ref/procedure-callingconvention-stack-0.log index 121a292ec..9f72690c7 100644 --- a/src/test/ref/procedure-callingconvention-stack-0.log +++ b/src/test/ref/procedure-callingconvention-stack-0.log @@ -90,8 +90,8 @@ Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Calling convention STACK_CALL adding prepare/execute/finalize for [5] (byte~) main::$0 ← call plus (byte) '0' (byte) 7 -Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,plus::OFFSET_STACK_A) -Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,plus::OFFSET_STACK_B) +Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,(const byte) plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,(const byte) plus::OFFSET_STACK_B) FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -118,8 +118,8 @@ main::@return: scope:[main] from main __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) - [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) + [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus @@ -217,11 +217,11 @@ plus: { .label a = 3 .label b = 4 .label return = 5 - // [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuz1=_stackgetbyte_vbuc1 + // [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -234,6 +234,10 @@ plus: { // plus::@return breturn: // [13] return (byte) plus::return#0 + // [13] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuz1 + lda.z return + tsx + sta STACK_BASE+1,x rts } // File Data @@ -241,16 +245,18 @@ plus: { REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ plus::a#0 ] Removing always clobbered register reg byte x as potential for zp ZP_BYTE:3 [ plus::a#0 ] Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:6 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] return (byte) plus::return#0 [ ] ( main:2::plus:6 [ ] ) always clobbers reg byte x Statement [5] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:6 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] return (byte) plus::return#0 [ ] ( main:2::plus:6 [ ] ) always clobbers reg byte x Potential registers zp ZP_BYTE:2 [ main::$0 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , Potential registers zp ZP_BYTE:3 [ plus::a#0 ] : zp ZP_BYTE:3 , reg byte y , Potential registers zp ZP_BYTE:4 [ plus::b#0 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y , @@ -261,11 +267,11 @@ Uplift Scope [plus] 4: zp ZP_BYTE:4 [ plus::b#0 ] 2: zp ZP_BYTE:3 [ plus::a#0 ] Uplift Scope [main] 2: zp ZP_BYTE:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 84 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:3 [ plus::a#0 ] reg byte a [ plus::return#0 ] -Uplifting [main] best 78 combination reg byte a [ main::$0 ] -Uplifting [] best 78 combination +Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:3 [ plus::a#0 ] reg byte a [ plus::return#0 ] +Uplifting [main] best 85 combination reg byte a [ main::$0 ] +Uplifting [] best 85 combination Attempting to uplift remaining variables inzp ZP_BYTE:3 [ plus::a#0 ] -Uplifting [plus] best 78 combination zp ZP_BYTE:3 [ plus::a#0 ] +Uplifting [plus] best 85 combination zp ZP_BYTE:3 [ plus::a#0 ] Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ plus::a#0 ] ASSEMBLER BEFORE OPTIMIZATION @@ -325,11 +331,11 @@ plus: { .const OFFSET_STACK_A = 0 .const OFFSET_STACK_B = 1 .label a = 2 - // [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 + // [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa @@ -339,6 +345,9 @@ plus: { // plus::@return breturn: // [13] return (byte) plus::return#0 + // [13] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+1,x rts } // File Data @@ -392,7 +401,7 @@ reg byte a [ plus::return#0 ] FINAL ASSEMBLER -Score: 60 +Score: 67 // File Comments // Test a procedure with calling convention stack @@ -442,11 +451,11 @@ plus: { .const OFFSET_STACK_A = 0 .const OFFSET_STACK_B = 1 .label a = 2 - // [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 + // [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // return a+b; @@ -456,6 +465,9 @@ plus: { // plus::@return // } // [13] return (byte) plus::return#0 + // [13] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+1,x rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-1.asm b/src/test/ref/procedure-callingconvention-stack-1.asm index b061638cc..3293ed5f3 100644 --- a/src/test/ref/procedure-callingconvention-stack-1.asm +++ b/src/test/ref/procedure-callingconvention-stack-1.asm @@ -27,5 +27,7 @@ plus: { lda STACK_BASE+OFFSET_STACK_B,x clc adc.z a + tsx + sta STACK_BASE+1,x rts } diff --git a/src/test/ref/procedure-callingconvention-stack-1.cfg b/src/test/ref/procedure-callingconvention-stack-1.cfg index 7d27d5cc1..37c87d1a7 100644 --- a/src/test/ref/procedure-callingconvention-stack-1.cfg +++ b/src/test/ref/procedure-callingconvention-stack-1.cfg @@ -22,8 +22,8 @@ main::@return: scope:[main] from main __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) - [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) + [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus diff --git a/src/test/ref/procedure-callingconvention-stack-1.log b/src/test/ref/procedure-callingconvention-stack-1.log index 121a292ec..9f72690c7 100644 --- a/src/test/ref/procedure-callingconvention-stack-1.log +++ b/src/test/ref/procedure-callingconvention-stack-1.log @@ -90,8 +90,8 @@ Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Calling convention STACK_CALL adding prepare/execute/finalize for [5] (byte~) main::$0 ← call plus (byte) '0' (byte) 7 -Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,plus::OFFSET_STACK_A) -Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,plus::OFFSET_STACK_B) +Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,(const byte) plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,(const byte) plus::OFFSET_STACK_B) FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -118,8 +118,8 @@ main::@return: scope:[main] from main __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) - [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) + [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) + [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus @@ -217,11 +217,11 @@ plus: { .label a = 3 .label b = 4 .label return = 5 - // [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuz1=_stackgetbyte_vbuc1 + // [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -234,6 +234,10 @@ plus: { // plus::@return breturn: // [13] return (byte) plus::return#0 + // [13] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuz1 + lda.z return + tsx + sta STACK_BASE+1,x rts } // File Data @@ -241,16 +245,18 @@ plus: { REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ plus::a#0 ] Removing always clobbered register reg byte x as potential for zp ZP_BYTE:3 [ plus::a#0 ] Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:6 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] return (byte) plus::return#0 [ ] ( main:2::plus:6 [ ] ) always clobbers reg byte x Statement [5] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] (byte~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a -Statement [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Statement [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:6 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] return (byte) plus::return#0 [ ] ( main:2::plus:6 [ ] ) always clobbers reg byte x Potential registers zp ZP_BYTE:2 [ main::$0 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y , Potential registers zp ZP_BYTE:3 [ plus::a#0 ] : zp ZP_BYTE:3 , reg byte y , Potential registers zp ZP_BYTE:4 [ plus::b#0 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y , @@ -261,11 +267,11 @@ Uplift Scope [plus] 4: zp ZP_BYTE:4 [ plus::b#0 ] 2: zp ZP_BYTE:3 [ plus::a#0 ] Uplift Scope [main] 2: zp ZP_BYTE:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 84 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:3 [ plus::a#0 ] reg byte a [ plus::return#0 ] -Uplifting [main] best 78 combination reg byte a [ main::$0 ] -Uplifting [] best 78 combination +Uplifting [plus] best 91 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:3 [ plus::a#0 ] reg byte a [ plus::return#0 ] +Uplifting [main] best 85 combination reg byte a [ main::$0 ] +Uplifting [] best 85 combination Attempting to uplift remaining variables inzp ZP_BYTE:3 [ plus::a#0 ] -Uplifting [plus] best 78 combination zp ZP_BYTE:3 [ plus::a#0 ] +Uplifting [plus] best 85 combination zp ZP_BYTE:3 [ plus::a#0 ] Allocated (was zp ZP_BYTE:3) zp ZP_BYTE:2 [ plus::a#0 ] ASSEMBLER BEFORE OPTIMIZATION @@ -325,11 +331,11 @@ plus: { .const OFFSET_STACK_A = 0 .const OFFSET_STACK_B = 1 .label a = 2 - // [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 + // [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // [12] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa @@ -339,6 +345,9 @@ plus: { // plus::@return breturn: // [13] return (byte) plus::return#0 + // [13] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+1,x rts } // File Data @@ -392,7 +401,7 @@ reg byte a [ plus::return#0 ] FINAL ASSEMBLER -Score: 60 +Score: 67 // File Comments // Test a procedure with calling convention stack @@ -442,11 +451,11 @@ plus: { .const OFFSET_STACK_A = 0 .const OFFSET_STACK_B = 1 .label a = 2 - // [10] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [10] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [11] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 + // [11] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // return a+b; @@ -456,6 +465,9 @@ plus: { // plus::@return // } // [13] return (byte) plus::return#0 + // [13] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+1,x rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-2.asm b/src/test/ref/procedure-callingconvention-stack-2.asm index 74df8cdfc..bc3a11172 100644 --- a/src/test/ref/procedure-callingconvention-stack-2.asm +++ b/src/test/ref/procedure-callingconvention-stack-2.asm @@ -51,5 +51,10 @@ plus: { lda.z return+1 adc.z b+1 sta.z return+1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } diff --git a/src/test/ref/procedure-callingconvention-stack-2.cfg b/src/test/ref/procedure-callingconvention-stack-2.cfg index f4cad78b9..30a6021e3 100644 --- a/src/test/ref/procedure-callingconvention-stack-2.cfg +++ b/src/test/ref/procedure-callingconvention-stack-2.cfg @@ -22,8 +22,8 @@ main::@return: scope:[main] from main __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) - [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) + [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus diff --git a/src/test/ref/procedure-callingconvention-stack-2.log b/src/test/ref/procedure-callingconvention-stack-2.log index 27c19a06d..4b64e336c 100644 --- a/src/test/ref/procedure-callingconvention-stack-2.log +++ b/src/test/ref/procedure-callingconvention-stack-2.log @@ -107,8 +107,8 @@ Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Calling convention STACK_CALL adding prepare/execute/finalize for [5] (word~) main::$0 ← call plus (word) $1234 (word) $2345 -Calling convention STACK_CALL replacing param((word) plus::a) with paramstack(word,plus::OFFSET_STACK_A) -Calling convention STACK_CALL replacing param((word) plus::b) with paramstack(word,plus::OFFSET_STACK_B) +Calling convention STACK_CALL replacing param((word) plus::a) with paramstack(word,(const byte) plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param((word) plus::b) with paramstack(word,(const byte) plus::OFFSET_STACK_B) FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -135,8 +135,8 @@ main::@return: scope:[main] from main __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) - [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) + [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus @@ -243,13 +243,13 @@ plus: { .label a = 4 .label b = 6 .label return = 8 - // [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 + // [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 + // [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -267,6 +267,12 @@ plus: { // plus::@return breturn: // [13] return (word) plus::return#0 + // [13] return (word) plus::return#0 -- _stackgetword_vbuc1=vwuz1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } // File Data @@ -275,9 +281,10 @@ REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] callprepare plus (word) $1234 (word) $2345 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] (word~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a Statement [8] *((const word*) SCREEN#0) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Statement [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:6 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] return (word) plus::return#0 [ ] ( main:2::plus:6 [ ] ) always clobbers reg byte a reg byte x Potential registers zp ZP_WORD:2 [ main::$0 ] : zp ZP_WORD:2 , Potential registers zp ZP_WORD:4 [ plus::a#0 ] : zp ZP_WORD:4 , Potential registers zp ZP_WORD:6 [ plus::b#0 ] : zp ZP_WORD:6 , @@ -288,9 +295,9 @@ Uplift Scope [plus] 4: zp ZP_WORD:6 [ plus::b#0 ] 2: zp ZP_WORD:4 [ plus::a#0 ] Uplift Scope [main] 2: zp ZP_WORD:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 146 combination zp ZP_WORD:6 [ plus::b#0 ] zp ZP_WORD:4 [ plus::a#0 ] zp ZP_WORD:8 [ plus::return#0 ] -Uplifting [main] best 146 combination zp ZP_WORD:2 [ main::$0 ] -Uplifting [] best 146 combination +Uplifting [plus] best 164 combination zp ZP_WORD:6 [ plus::b#0 ] zp ZP_WORD:4 [ plus::a#0 ] zp ZP_WORD:8 [ plus::return#0 ] +Uplifting [main] best 164 combination zp ZP_WORD:2 [ main::$0 ] +Uplifting [] best 164 combination Coalescing zero page register [ zp ZP_WORD:4 [ plus::a#0 ] ] with [ zp ZP_WORD:8 [ plus::return#0 ] ] - score: 1 Coalescing zero page register [ zp ZP_WORD:4 [ plus::a#0 plus::return#0 ] ] with [ zp ZP_WORD:2 [ main::$0 ] ] Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ plus::a#0 plus::return#0 main::$0 ] @@ -367,13 +374,13 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 + // [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 + // [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -391,6 +398,12 @@ plus: { // plus::@return breturn: // [13] return (word) plus::return#0 + // [13] return (word) plus::return#0 -- _stackgetword_vbuc1=vwuz1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } // File Data @@ -442,7 +455,7 @@ zp ZP_WORD:4 [ plus::b#0 ] FINAL ASSEMBLER -Score: 128 +Score: 146 // File Comments // Test a procedure with calling convention stack - and enough parameters to use fast ASM for cleaning stack @@ -506,13 +519,13 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 + // [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 + // [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -530,6 +543,12 @@ plus: { // plus::@return // } // [13] return (word) plus::return#0 + // [13] return (word) plus::return#0 -- _stackgetword_vbuc1=vwuz1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-3.asm b/src/test/ref/procedure-callingconvention-stack-3.asm index 6c38e74b9..acca2e938 100644 --- a/src/test/ref/procedure-callingconvention-stack-3.asm +++ b/src/test/ref/procedure-callingconvention-stack-3.asm @@ -50,5 +50,10 @@ plus: { lda.z return+1 adc.z b+1 sta.z return+1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } diff --git a/src/test/ref/procedure-callingconvention-stack-3.cfg b/src/test/ref/procedure-callingconvention-stack-3.cfg index 26c06ac4c..a6f31f3da 100644 --- a/src/test/ref/procedure-callingconvention-stack-3.cfg +++ b/src/test/ref/procedure-callingconvention-stack-3.cfg @@ -22,8 +22,8 @@ main::@return: scope:[main] from main __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) - [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) + [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus diff --git a/src/test/ref/procedure-callingconvention-stack-3.log b/src/test/ref/procedure-callingconvention-stack-3.log index 901fe92d4..0776f09ac 100644 --- a/src/test/ref/procedure-callingconvention-stack-3.log +++ b/src/test/ref/procedure-callingconvention-stack-3.log @@ -104,8 +104,8 @@ Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Calling convention STACK_CALL adding prepare/execute/finalize for [5] (word~) main::$0 ← call plus (byte) '0' (byte) 7 -Calling convention STACK_CALL replacing param((word) plus::a) with paramstack(word,plus::OFFSET_STACK_A) -Calling convention STACK_CALL replacing param((word) plus::b) with paramstack(word,plus::OFFSET_STACK_B) +Calling convention STACK_CALL replacing param((word) plus::a) with paramstack(word,(const byte) plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param((word) plus::b) with paramstack(word,(const byte) plus::OFFSET_STACK_B) FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -132,8 +132,8 @@ main::@return: scope:[main] from main __stackcall (word()) plus((word) plus::a , (word) plus::b) plus: scope:[plus] from - [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) - [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) + [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) + [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus @@ -239,13 +239,13 @@ plus: { .label a = 4 .label b = 6 .label return = 8 - // [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 + // [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 + // [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -263,6 +263,12 @@ plus: { // plus::@return breturn: // [13] return (word) plus::return#0 + // [13] return (word) plus::return#0 -- _stackgetword_vbuc1=vwuz1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } // File Data @@ -271,9 +277,10 @@ REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] callprepare plus (byte) '0' (byte) 7 [ ] ( main:2 [ ] ) always clobbers reg byte a Statement [7] (word~) main::$0 ← callfinalize plus [ main::$0 ] ( main:2 [ main::$0 ] ) always clobbers reg byte a Statement [8] *((const word*) SCREEN#0) ← (word~) main::$0 [ ] ( main:2 [ ] ) always clobbers reg byte a -Statement [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:6 [ plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:6 [ plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Statement [12] (word) plus::return#0 ← (word) plus::a#0 + (word) plus::b#0 [ plus::return#0 ] ( main:2::plus:6 [ plus::return#0 ] ) always clobbers reg byte a +Statement [13] return (word) plus::return#0 [ ] ( main:2::plus:6 [ ] ) always clobbers reg byte a reg byte x Potential registers zp ZP_WORD:2 [ main::$0 ] : zp ZP_WORD:2 , Potential registers zp ZP_WORD:4 [ plus::a#0 ] : zp ZP_WORD:4 , Potential registers zp ZP_WORD:6 [ plus::b#0 ] : zp ZP_WORD:6 , @@ -284,9 +291,9 @@ Uplift Scope [plus] 4: zp ZP_WORD:6 [ plus::b#0 ] 2: zp ZP_WORD:4 [ plus::a#0 ] Uplift Scope [main] 2: zp ZP_WORD:2 [ main::$0 ] Uplift Scope [] -Uplifting [plus] best 136 combination zp ZP_WORD:6 [ plus::b#0 ] zp ZP_WORD:4 [ plus::a#0 ] zp ZP_WORD:8 [ plus::return#0 ] -Uplifting [main] best 136 combination zp ZP_WORD:2 [ main::$0 ] -Uplifting [] best 136 combination +Uplifting [plus] best 154 combination zp ZP_WORD:6 [ plus::b#0 ] zp ZP_WORD:4 [ plus::a#0 ] zp ZP_WORD:8 [ plus::return#0 ] +Uplifting [main] best 154 combination zp ZP_WORD:2 [ main::$0 ] +Uplifting [] best 154 combination Coalescing zero page register [ zp ZP_WORD:4 [ plus::a#0 ] ] with [ zp ZP_WORD:8 [ plus::return#0 ] ] - score: 1 Coalescing zero page register [ zp ZP_WORD:4 [ plus::a#0 plus::return#0 ] ] with [ zp ZP_WORD:2 [ main::$0 ] ] Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ plus::a#0 plus::return#0 main::$0 ] @@ -362,13 +369,13 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 + // [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 + // [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -386,6 +393,12 @@ plus: { // plus::@return breturn: // [13] return (word) plus::return#0 + // [13] return (word) plus::return#0 -- _stackgetword_vbuc1=vwuz1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } // File Data @@ -437,7 +450,7 @@ zp ZP_WORD:4 [ plus::b#0 ] FINAL ASSEMBLER -Score: 118 +Score: 136 // File Comments // Test a procedure with calling convention stack @@ -500,13 +513,13 @@ plus: { .label a = 2 .label b = 4 .label return = 2 - // [10] (word) plus::a#0 ← paramstack(word,plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 + // [10] (word) plus::a#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_A) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a lda STACK_BASE+OFFSET_STACK_A+1,x sta.z a+1 - // [11] (word) plus::b#0 ← paramstack(word,plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 + // [11] (word) plus::b#0 ← paramstack(word,(const byte) plus::OFFSET_STACK_B) -- vwuz1=_stackgetword_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -524,6 +537,12 @@ plus: { // plus::@return // } // [13] return (word) plus::return#0 + // [13] return (word) plus::return#0 -- _stackgetword_vbuc1=vwuz1 + tsx + lda.z return + sta STACK_BASE+2,x + lda.z return+1 + sta STACK_BASE+2+1,x rts } // File Data diff --git a/src/test/ref/procedure-callingconvention-stack-4.asm b/src/test/ref/procedure-callingconvention-stack-4.asm index cc0338948..f5759ae04 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.asm +++ b/src/test/ref/procedure-callingconvention-stack-4.asm @@ -39,5 +39,7 @@ plus: { lda STACK_BASE+OFFSET_STACK_B,x clc adc.z a + tsx + sta STACK_BASE+1,x rts } diff --git a/src/test/ref/procedure-callingconvention-stack-4.cfg b/src/test/ref/procedure-callingconvention-stack-4.cfg index be222f493..2ab0e12ea 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.cfg +++ b/src/test/ref/procedure-callingconvention-stack-4.cfg @@ -29,8 +29,8 @@ main::@return: scope:[main] from main::@1 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) - [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) + [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) + [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus diff --git a/src/test/ref/procedure-callingconvention-stack-4.log b/src/test/ref/procedure-callingconvention-stack-4.log index 3cb2fd89f..c74350be4 100644 --- a/src/test/ref/procedure-callingconvention-stack-4.log +++ b/src/test/ref/procedure-callingconvention-stack-4.log @@ -170,8 +170,8 @@ Adding NOP phi() at start of @1 Adding NOP phi() at start of @end Adding NOP phi() at start of main Calling convention STACK_CALL adding prepare/execute/finalize for [7] (byte) main::w#0 ← call plus (byte) '0' (byte) main::v#0 -Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,plus::OFFSET_STACK_A) -Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,plus::OFFSET_STACK_B) +Calling convention STACK_CALL replacing param((byte) plus::a) with paramstack(byte,(const byte) plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param((byte) plus::b) with paramstack(byte,(const byte) plus::OFFSET_STACK_B) FINAL CONTROL FLOW GRAPH @begin: scope:[] from @@ -205,8 +205,8 @@ main::@return: scope:[main] from main::@1 __stackcall (byte()) plus((byte) plus::a , (byte) plus::b) plus: scope:[plus] from - [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) - [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) + [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) + [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 to:plus::@return plus::@return: scope:[plus] from plus @@ -352,11 +352,11 @@ plus: { .label a = 6 .label b = 7 .label return = 8 - // [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuz1=_stackgetbyte_vbuc1 + // [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x sta.z b @@ -369,6 +369,10 @@ plus: { // plus::@return breturn: // [18] return (byte) plus::return#0 + // [18] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuz1 + lda.z return + tsx + sta STACK_BASE+1,x rts } // File Data @@ -378,18 +382,20 @@ Statement [7] callprepare plus (byte) '0' (byte) main::v#0 [ main::a#2 ] ( main Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::a#2 main::a#1 ] Statement [9] (byte) main::w#0 ← callfinalize plus [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a Statement [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a -Statement [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::a#2 main::a#1 ] -Statement [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Removing always clobbered register reg byte a as potential for zp ZP_BYTE:6 [ plus::a#0 ] Removing always clobbered register reg byte x as potential for zp ZP_BYTE:6 [ plus::a#0 ] Statement [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a +Statement [18] return (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x Statement [7] callprepare plus (byte) '0' (byte) main::v#0 [ main::a#2 ] ( main:2 [ main::a#2 ] ) always clobbers reg byte a Statement [9] (byte) main::w#0 ← callfinalize plus [ main::a#2 main::w#0 ] ( main:2 [ main::a#2 main::w#0 ] ) always clobbers reg byte a Statement [10] (byte~) main::$2 ← (byte) main::w#0 + (byte) main::a#2 [ main::a#2 main::$2 ] ( main:2 [ main::a#2 main::$2 ] ) always clobbers reg byte a -Statement [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x -Statement [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x +Statement [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) [ plus::a#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 ] ) always clobbers reg byte a reg byte x +Statement [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( main:2::plus:8 [ main::a#2 plus::a#0 plus::b#0 ] ) always clobbers reg byte a reg byte x Statement [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 [ plus::return#0 ] ( main:2::plus:8 [ main::a#2 plus::return#0 ] ) always clobbers reg byte a +Statement [18] return (byte) plus::return#0 [ ] ( main:2::plus:8 [ main::a#2 ] ) always clobbers reg byte x Potential registers zp ZP_BYTE:2 [ main::a#2 main::a#1 ] : zp ZP_BYTE:2 , reg byte y , Potential registers zp ZP_BYTE:3 [ main::v#0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y , Potential registers zp ZP_BYTE:4 [ main::w#0 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y , @@ -403,12 +409,12 @@ Uplift Scope [main] 22.79: zp ZP_BYTE:2 [ main::a#2 main::a#1 ] 22: zp ZP_BYTE:5 Uplift Scope [plus] 4: zp ZP_BYTE:7 [ plus::b#0 ] 2: zp ZP_BYTE:6 [ plus::a#0 ] 2: zp ZP_BYTE:8 [ plus::return#0 ] Uplift Scope [] -Uplifting [main] best 651 combination reg byte y [ main::a#2 main::a#1 ] reg byte a [ main::$2 ] reg byte x [ main::v#0 ] reg byte a [ main::w#0 ] +Uplifting [main] best 661 combination reg byte y [ main::a#2 main::a#1 ] reg byte a [ main::$2 ] reg byte x [ main::v#0 ] reg byte a [ main::w#0 ] Limited combination testing to 100 combinations of 128 possible. -Uplifting [plus] best 642 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:6 [ plus::a#0 ] reg byte a [ plus::return#0 ] -Uplifting [] best 642 combination +Uplifting [plus] best 649 combination reg byte a [ plus::b#0 ] zp ZP_BYTE:6 [ plus::a#0 ] reg byte a [ plus::return#0 ] +Uplifting [] best 649 combination Attempting to uplift remaining variables inzp ZP_BYTE:6 [ plus::a#0 ] -Uplifting [plus] best 642 combination zp ZP_BYTE:6 [ plus::a#0 ] +Uplifting [plus] best 649 combination zp ZP_BYTE:6 [ plus::a#0 ] Allocated (was zp ZP_BYTE:6) zp ZP_BYTE:2 [ plus::a#0 ] ASSEMBLER BEFORE OPTIMIZATION @@ -493,11 +499,11 @@ plus: { .const OFFSET_STACK_A = 0 .const OFFSET_STACK_B = 1 .label a = 2 - // [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 + // [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // [17] (byte) plus::return#0 ← (byte) plus::a#0 + (byte) plus::b#0 -- vbuaa=vbuz1_plus_vbuaa @@ -507,6 +513,9 @@ plus: { // plus::@return breturn: // [18] return (byte) plus::return#0 + // [18] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+1,x rts } // File Data @@ -578,7 +587,7 @@ reg byte a [ plus::return#0 ] FINAL ASSEMBLER -Score: 537 +Score: 544 // File Comments // Test a procedure with calling convention stack @@ -652,11 +661,11 @@ plus: { .const OFFSET_STACK_A = 0 .const OFFSET_STACK_B = 1 .label a = 2 - // [15] (byte) plus::a#0 ← paramstack(byte,plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 + // [15] (byte) plus::a#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_A) -- vbuz1=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_A,x sta.z a - // [16] (byte) plus::b#0 ← paramstack(byte,plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 + // [16] (byte) plus::b#0 ← paramstack(byte,(const byte) plus::OFFSET_STACK_B) -- vbuaa=_stackgetbyte_vbuc1 tsx lda STACK_BASE+OFFSET_STACK_B,x // return a+b; @@ -666,6 +675,9 @@ plus: { // plus::@return // } // [18] return (byte) plus::return#0 + // [18] return (byte) plus::return#0 -- _stackgetbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+1,x rts } // File Data