diff --git a/compiler/examples/comparisons_byte.p8 b/compiler/examples/comparisons_byte.p8 index 4f513a181..2676f7335 100644 --- a/compiler/examples/comparisons_byte.p8 +++ b/compiler/examples/comparisons_byte.p8 @@ -9,20 +9,10 @@ byte v2 ubyte cr - ; done: - ; ubyte all 6 comparisons - ; byte all 6 comparisons - - - ; check stack usage: - rsave() c64.STROUT("signed byte ") - rrestore() - rsave() c64scr.print_byte_decimal(X) c64.CHROUT(' ') - rrestore() cr=v1==v2 cr=v1==v2 @@ -49,103 +39,63 @@ cr=v1>=v2 cr=v1>=v2 - rsave() c64scr.print_byte_decimal(X) c64.CHROUT('\n') - rrestore() ; comparisons: - rsave() v1=-20 v2=125 c64.STROUT("v1=-20, v2=125\n") - rrestore() compare() - rsave() v1=80 v2=80 c64.STROUT("v1 = v2 = 80\n") - rrestore() - compare() - rsave() v1=20 v2=-111 c64.STROUT("v1=20, v2=-111\n") - rrestore() - compare() + c64scr.print_byte_decimal(X) + c64.CHROUT('\n') + return + sub compare() { - rsave() c64.STROUT(" == != < > <= >=\n") - rrestore() - if v1==v2 { - rsave() + if v1==v2 c64.STROUT(" Q ") - rrestore() - } else { - rsave() + else c64.STROUT(" . ") - rrestore() - } - if v1!=v2 { - rsave() + if v1!=v2 c64.STROUT(" Q ") - rrestore() - } else { - rsave() + else c64.STROUT(" . ") - rrestore() - } - if v1v2 { - rsave() + if v1>v2 c64.STROUT(" Q ") - rrestore() - } else { - rsave() + else c64.STROUT(" . ") - rrestore() - } - if v1<=v2 { - rsave() + if v1<=v2 c64.STROUT(" Q ") - rrestore() - } else { - rsave() + else c64.STROUT(" . ") - rrestore() - } - - if v1>=v2 { - rsave() + if v1>=v2 c64.STROUT(" Q ") - rrestore() - } else { - rsave() + else c64.STROUT(" . ") - rrestore() - } c64.CHROUT('\n') - } } diff --git a/compiler/examples/comparisons_float.p8 b/compiler/examples/comparisons_float.p8 index 1a84dd726..dd8a3e2a6 100644 --- a/compiler/examples/comparisons_float.p8 +++ b/compiler/examples/comparisons_float.p8 @@ -11,22 +11,10 @@ float v2 ubyte cr - ; done: - ; ubyte all 6 comparisons - ; byte all 6 comparisons - ; uword all 6 comparisons - ; word all 6 comparisons - ; float all 6 comparisons - - ; check stack usage: - rsave() c64.STROUT("floating point ") - rrestore() - rsave() c64scr.print_byte_decimal(X) c64.CHROUT(' ') - rrestore() cr=v1==v2 cr=v1==v2 @@ -53,123 +41,81 @@ cr=v1>=v2 cr=v1>=v2 - rsave() c64scr.print_byte_decimal(X) c64.CHROUT('\n') - rrestore() ; comparisons: - rsave() v1=20 v2=666.66 c64.STROUT("v1=20, v2=666.66\n") - rrestore() compare() - rsave() v1=-20 v2=666.66 c64.STROUT("v1=-20, v2=666.66\n") - rrestore() compare() - rsave() v1=666.66 v2=555.55 c64.STROUT("v1=666.66, v2=555.55\n") - rrestore() compare() - rsave() v1=3.1415 v2=-3.1415 c64.STROUT("v1 = 3.1415, v2 = -3.1415\n") - rrestore() compare() - rsave() v1=3.1415 v2=3.1415 c64.STROUT("v1 = v2 = 3.1415\n") - rrestore() compare() - rsave() v1=0 v2=0 c64.STROUT("v1 = v2 = 0\n") - rrestore() compare() - sub compare() { - rsave() - c64.STROUT(" == != < > <= >=\n") - rrestore() - - if v1==v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - if v1!=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1<=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - - if v1>=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } + c64scr.print_byte_decimal(X) c64.CHROUT('\n') + return + + sub compare() { + c64.STROUT(" == != < > <= >=\n") + + if v1==v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + if v1!=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1<=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1>=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + c64.CHROUT('\n') } + } } diff --git a/compiler/examples/comparisons_ubyte.p8 b/compiler/examples/comparisons_ubyte.p8 index 276fbdea0..a6249e577 100644 --- a/compiler/examples/comparisons_ubyte.p8 +++ b/compiler/examples/comparisons_ubyte.p8 @@ -9,19 +9,10 @@ ubyte v2 ubyte cr - ; done: - ; ubyte all 6 comparisons - - - ; check stack usage: - rsave() c64.STROUT("unsigned byte ") - rrestore() - rsave() c64scr.print_byte_decimal(X) c64.CHROUT(' ') - rrestore() cr=v1==v2 cr=v1==v2 @@ -48,102 +39,62 @@ cr=v1>=v2 cr=v1>=v2 - rsave() c64scr.print_byte_decimal(X) c64.CHROUT('\n') - rrestore() ; comparisons: - rsave() v1=20 v2=199 c64.STROUT("v1=20, v2=199\n") - rrestore() compare() - rsave() v1=80 v2=80 c64.STROUT("v1 = v2 = 80\n") - rrestore() - compare() - rsave() v1=220 v2=10 c64.STROUT("v1=220, v2=10\n") - rrestore() - compare() - - sub compare() { - rsave() - c64.STROUT(" == != < > <= >=\n") - rrestore() - - if v1==v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - if v1!=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1<=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - - if v1>=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } + c64scr.print_byte_decimal(X) c64.CHROUT('\n') + return + + sub compare() { + c64.STROUT(" == != < > <= >=\n") + + if v1==v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + if v1!=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1<=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1>=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + c64.CHROUT('\n') } diff --git a/compiler/examples/comparisons_uword.p8 b/compiler/examples/comparisons_uword.p8 index 5f7c407a4..d054ec465 100644 --- a/compiler/examples/comparisons_uword.p8 +++ b/compiler/examples/comparisons_uword.p8 @@ -9,21 +9,10 @@ uword v2 ubyte cr - ; done: - ; ubyte all 6 comparisons - ; byte all 6 comparisons - ; uword all 6 comparisons - - - ; check stack usage: - rsave() c64.STROUT("unsigned word ") - rrestore() - rsave() c64scr.print_byte_decimal(X) c64.CHROUT(' ') - rrestore() cr=v1==v2 cr=v1==v2 @@ -50,141 +39,92 @@ cr=v1>=v2 cr=v1>=v2 - rsave() c64scr.print_byte_decimal(X) c64.CHROUT('\n') - rrestore() ; comparisons: - rsave() v1=20 v2=$00aa c64.STROUT("v1=20, v2=$00aa\n") - rrestore() compare() - rsave() v1=20 v2=$ea00 c64.STROUT("v1=20, v2=$ea00\n") - rrestore() compare() - rsave() v1=$c400 v2=$22 c64.STROUT("v1=$c400, v2=$22\n") - rrestore() compare() - rsave() v1=$c400 v2=$2a00 c64.STROUT("v1=$c400, v2=$2a00\n") - rrestore() compare() - rsave() v1=$c433 v2=$2a00 c64.STROUT("v1=$c433, v2=$2a00\n") - rrestore() compare() - rsave() v1=$c433 v2=$2aff c64.STROUT("v1=$c433, v2=$2aff\n") - rrestore() compare() - rsave() v1=$aabb v2=$aabb c64.STROUT("v1 = v2 = aabb\n") - rrestore() compare() - rsave() v1=$aa00 v2=$aa00 c64.STROUT("v1 = v2 = aa00\n") - rrestore() compare() - rsave() v1=$aa v2=$aa c64.STROUT("v1 = v2 = aa\n") - rrestore() compare() - sub compare() { - rsave() - c64.STROUT(" == != < > <= >=\n") - rrestore() - - if v1==v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - if v1!=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1<=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - - if v1>=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } + c64scr.print_byte_decimal(X) c64.CHROUT('\n') + return + + sub compare() { + c64.STROUT(" == != < > <= >=\n") + + if v1==v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + if v1!=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1<=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1>=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + c64.CHROUT('\n') } diff --git a/compiler/examples/comparisons_word.p8 b/compiler/examples/comparisons_word.p8 index 565db4bc6..011f8685f 100644 --- a/compiler/examples/comparisons_word.p8 +++ b/compiler/examples/comparisons_word.p8 @@ -9,22 +9,11 @@ word v2 ubyte cr - ; done: - ; ubyte all 6 comparisons - ; byte all 6 comparisons - ; uword all 6 comparisons - ; word all 6 comparisons - - ; check stack usage: - rsave() c64.STROUT("signed word ") - rrestore() - rsave() c64scr.print_byte_decimal(X) c64.CHROUT(' ') - rrestore() cr=v1==v2 cr=v1==v2 @@ -51,191 +40,128 @@ cr=v1>=v2 cr=v1>=v2 - rsave() c64scr.print_byte_decimal(X) c64.CHROUT('\n') - rrestore() ; comparisons: - rsave() v1=20 v2=$00aa c64.STROUT("v1=20, v2=$00aa\n") - rrestore() compare() - rsave() v1=20 v2=$7a00 c64.STROUT("v1=20, v2=$7a00\n") - rrestore() compare() - rsave() v1=$7400 v2=$22 c64.STROUT("v1=$7400, v2=$22\n") - rrestore() compare() - rsave() v1=$7400 v2=$2a00 c64.STROUT("v1=$7400, v2=$2a00\n") - rrestore() compare() - rsave() v1=$7433 v2=$2a00 c64.STROUT("v1=$7433, v2=$2a00\n") - rrestore() compare() - rsave() v1=$7433 v2=$2aff c64.STROUT("v1=$7433, v2=$2aff\n") - rrestore() compare() ; with negative numbers: - rsave() v1=-512 v2=$00aa c64.STROUT("v1=-512, v2=$00aa\n") - rrestore() compare() - rsave() v1=-512 v2=$7a00 c64.STROUT("v1=-512, v2=$7a00\n") - rrestore() compare() - rsave() v1=$7400 v2=-512 c64.STROUT("v1=$7400, v2=-512\n") - rrestore() compare() - rsave() v1=-20000 v2=-1000 c64.STROUT("v1=-20000, v2=-1000\n") - rrestore() compare() - rsave() v1=-1000 v2=-20000 c64.STROUT("v1=-1000, v2=-20000\n") - rrestore() compare() - rsave() v1=-1 v2=32767 c64.STROUT("v1=-1, v2=32767\n") - rrestore() compare() - rsave() v1=32767 v2=-1 c64.STROUT("v1=32767, v2=-1\n") - rrestore() compare() - rsave() v1=$7abb v2=$7abb c64.STROUT("v1 = v2 = 7abb\n") - rrestore() compare() - rsave() v1=$7a00 v2=$7a00 c64.STROUT("v1 = v2 = 7a00\n") - rrestore() compare() - rsave() v1=$aa v2=$aa c64.STROUT("v1 = v2 = aa\n") - rrestore() compare() - sub compare() { - rsave() - c64.STROUT(" == != < > <= >=\n") - rrestore() - - if v1==v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - if v1!=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1<=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - - if v1>=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } + c64scr.print_byte_decimal(X) c64.CHROUT('\n') + return + + sub compare() { + c64.STROUT(" == != < > <= >=\n") + + if v1==v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + if v1!=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1<=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1>=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + c64.CHROUT('\n') } diff --git a/compiler/examples/hello.p8 b/compiler/examples/hello.p8 index 0d775be30..20e80bb24 100644 --- a/compiler/examples/hello.p8 +++ b/compiler/examples/hello.p8 @@ -9,17 +9,15 @@ sub start() { c64.EXTCOL = 5 c64.BGCOL0 = 0 c64.COLOR = 1 - c64.VMCSB = %10111 + c64.VMCSB |= 2 - ; use kernel routine to write text (sorry, loops don't work in asm yet) - c64.CHROUT('H') - c64.CHROUT('e') - c64.CHROUT('l') - c64.CHROUT('l') - c64.CHROUT('o') - c64.CHROUT('!') - c64.CHROUT('\n') + ; use kernel routine to write text + c64.STROUT("Hello!\n") + str question = "How are you?\n" + for ubyte c in 0 to len(question) { + c64.CHROUT(question[c]) + } return } diff --git a/compiler/examples/numbergame-c64.p8 b/compiler/examples/numbergame-c64.p8 index 8ce948e64..5eed2016d 100644 --- a/compiler/examples/numbergame-c64.p8 +++ b/compiler/examples/numbergame-c64.p8 @@ -41,11 +41,9 @@ ask_guess: c64scr.input_chars(guessstr) c64.CHROUT('\n') freadstr_arg = guessstr - rsave() c64.FREADSTR(Y) A, Y = c64flt.GETADRAY() guess=A - rrestore() c64.EXTCOL=guess ; @debug c64.BGCOL0=secretnumber ;@debug if(guess==secretnumber) { ; @todo equal_b doesn't work diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index f848bad6d..dd8a3e2a6 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -1,28 +1,20 @@ %import c64utils %import mathlib +%option enable_floats + ~ main { sub start() { - uword v1 - uword v2 + float v1 + float v2 ubyte cr - ; done: - ; ubyte all 6 comparisons - ; byte all 6 comparisons - - - ; check stack usage: - rsave() - c64.STROUT("unsigned word ") - rrestore() - rsave() + c64.STROUT("floating point ") c64scr.print_byte_decimal(X) c64.CHROUT(' ') - rrestore() cr=v1==v2 cr=v1==v2 @@ -49,144 +41,81 @@ cr=v1>=v2 cr=v1>=v2 - rsave() c64scr.print_byte_decimal(X) c64.CHROUT('\n') - rrestore() ; comparisons: - rsave() v1=20 - v2=$00aa - c64.STROUT("v1=20, v2=$00aa\n") - rrestore() + v2=666.66 + c64.STROUT("v1=20, v2=666.66\n") compare() - rsave() - v1=20 - v2=$ea00 - c64.STROUT("v1=20, v2=$ea00\n") - rrestore() + v1=-20 + v2=666.66 + c64.STROUT("v1=-20, v2=666.66\n") compare() - rsave() - v1=$c400 - v2=$22 - c64.STROUT("v1=$c400, v2=$22\n") - rrestore() + v1=666.66 + v2=555.55 + c64.STROUT("v1=666.66, v2=555.55\n") compare() - rsave() - v1=$c400 - v2=$2a00 - c64.STROUT("v1=$c400, v2=$2a00\n") - rrestore() + v1=3.1415 + v2=-3.1415 + c64.STROUT("v1 = 3.1415, v2 = -3.1415\n") compare() - rsave() - v1=$c433 - v2=$2a00 - c64.STROUT("v1=$c433, v2=$2a00\n") - rrestore() + v1=3.1415 + v2=3.1415 + c64.STROUT("v1 = v2 = 3.1415\n") compare() - rsave() - v1=$c433 - v2=$2aff - c64.STROUT("v1=$c433, v2=$2aff\n") - rrestore() + v1=0 + v2=0 + c64.STROUT("v1 = v2 = 0\n") compare() -; rsave() -; v1=$aabb -; v2=$aabb -; c64.STROUT("v1 = v2 = aabb\n") -; rrestore() -; compare() -; -; rsave() -; v1=$aa00 -; v2=$aa00 -; c64.STROUT("v1 = v2 = aa00\n") -; rrestore() -; compare() -; -; rsave() -; v1=$aa -; v2=$aa -; c64.STROUT("v1 = v2 = aa\n") -; rrestore() -; compare() - - sub compare() { - rsave() - c64.STROUT(" == != < > <= >=\n") - rrestore() - - if v1==v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - if v1!=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - if v1<=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } - - - if v1>=v2 { - rsave() - c64.STROUT(" Q ") - rrestore() - } else { - rsave() - c64.STROUT(" . ") - rrestore() - } + c64scr.print_byte_decimal(X) c64.CHROUT('\n') + return + + sub compare() { + c64.STROUT(" == != < > <= >=\n") + + if v1==v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + if v1!=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1<=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + + if v1>=v2 + c64.STROUT(" Q ") + else + c64.STROUT(" . ") + c64.CHROUT('\n') } + } } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 8bb386a66..662d3c0b1 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -763,10 +763,14 @@ private class StatementTranslator(private val prog: IntermediateProgram, private fun translateSubroutineCall(subroutine: Subroutine, arguments: List, callPosition: Position) { // evaluate the arguments and assign them into the subroutine's argument variables. + var restoreX = Register.X in subroutine.asmClobbers if(subroutine.asmParameterRegisters.isNotEmpty()) { if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size) throw CompilerException("no support for mix of register and non-register subroutine arguments") + if(restoreX) + prog.instr(Opcode.RSAVEX) + // only register arguments (or status-flag bits) var carryParam: Boolean? = null for(arg in arguments.zip(subroutine.asmParameterRegisters)) { @@ -783,7 +787,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, translate(assign) } X -> { - // TODO: save X on stack & restore after call + if(!restoreX) { + prog.instr(Opcode.RSAVEX) + restoreX = true + } val assign = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, arg.first, callPosition) assign.linkParents(arguments[0].parent) translate(assign) @@ -794,7 +801,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, translate(assign) } AX -> { - // TODO: save X on stack & restore after call + if(!restoreX) { + prog.instr(Opcode.RSAVEX) + restoreX = true + } val valueA: IExpression val valueX: IExpression val paramDt = arg.first.resultingDatatype(namespace, heap) @@ -847,7 +857,10 @@ private class StatementTranslator(private val prog: IntermediateProgram, } } XY -> { - // TODO: save X on stack & restore after call + if(!restoreX) { + prog.instr(Opcode.RSAVEX) + restoreX = true + } val valueX: IExpression val valueY: IExpression val paramDt = arg.first.resultingDatatype(namespace, heap) @@ -882,7 +895,6 @@ private class StatementTranslator(private val prog: IntermediateProgram, true -> prog.instr(Opcode.SEC) false -> prog.instr(Opcode.CLC) } - } else { // only regular (non-register) arguments for (arg in arguments.zip(subroutine.parameters)) { @@ -892,6 +904,8 @@ private class StatementTranslator(private val prog: IntermediateProgram, } } prog.instr(Opcode.CALL, callLabel = subroutine.scopedname) + if(restoreX) + prog.instr(Opcode.RRESTOREX) } private fun translateBinaryOperator(operator: String, dt: DataType) { diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt index 40349f11e..2f7a04c90 100644 --- a/compiler/src/prog8/compiler/intermediate/Opcode.kt +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -219,7 +219,9 @@ enum class Opcode { SEI, // set irq-disable status flag CLI, // clear irq-disable status flag RSAVE, // save all internal registers and status flags + RSAVEX, // save just X (the evaluation stack pointer) RRESTORE, // restore all internal registers and status flags + RRESTOREX, // restore just X (the evaluation stack pointer) NOP, // do nothing BREAKPOINT, // breakpoint TERMINATE, // end the program diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 3b3dd2199..5018cf003 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -424,6 +424,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, // restore all registers and cpu status flag " pla | tay | pla | tax | pla | plp" } + Opcode.RSAVEX -> " stx ${C64Zeropage.SCRATCH_REG_X}" + Opcode.RRESTOREX -> " ldx ${C64Zeropage.SCRATCH_REG_X}" Opcode.DISCARD_BYTE -> " inx" Opcode.DISCARD_WORD -> " inx" Opcode.DISCARD_FLOAT -> " inx | inx | inx" diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index 14c6a22d5..72bc36a08 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -1377,6 +1377,8 @@ class StackVm(private var traceOutputFile: String?) { P_carry = evalstack.pop().asBooleanValue P_irqd = evalstack.pop().asBooleanValue } + Opcode.RSAVEX -> evalstack.push(variables["X"]) + Opcode.RRESTOREX -> variables["X"] = evalstack.pop() Opcode.INLINE_ASSEMBLY -> throw VmExecutionException("stackVm doesn't support executing inline assembly code") Opcode.PUSH_ADDR_HEAPVAR -> { val heapId = variables[ins.callLabel]!!.heapId diff --git a/docs/source/programming.rst b/docs/source/programming.rst index eb19b07b8..8c0faa426 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -650,6 +650,9 @@ rsave() Saves the CPU registers and the status flags. You can now more or less 'safely' use the registers directly, until you restore them again so the generated code can carry on normally. + Note: it's not needed to rsave() before an asm subroutine that clobbers the X register + (which is used as the internal evaluation stack pointer). + The compiler will take care of this situation automatically. rrestore() Restores the CPU registers and the status flags from previously saved values.