save X register automatically when calling sub that clobbers X

This commit is contained in:
Irmen de Jong 2018-12-09 19:48:59 +01:00
parent b8150f645d
commit f070dc22bb
13 changed files with 249 additions and 588 deletions

View File

@ -9,20 +9,10 @@
byte v2 byte v2
ubyte cr ubyte cr
; done:
; ubyte all 6 comparisons
; byte all 6 comparisons
; check stack usage: ; check stack usage:
rsave()
c64.STROUT("signed byte ") c64.STROUT("signed byte ")
rrestore()
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT(' ') c64.CHROUT(' ')
rrestore()
cr=v1==v2 cr=v1==v2
cr=v1==v2 cr=v1==v2
@ -49,103 +39,63 @@
cr=v1>=v2 cr=v1>=v2
cr=v1>=v2 cr=v1>=v2
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
rrestore()
; comparisons: ; comparisons:
rsave()
v1=-20 v1=-20
v2=125 v2=125
c64.STROUT("v1=-20, v2=125\n") c64.STROUT("v1=-20, v2=125\n")
rrestore()
compare() compare()
rsave()
v1=80 v1=80
v2=80 v2=80
c64.STROUT("v1 = v2 = 80\n") c64.STROUT("v1 = v2 = 80\n")
rrestore()
compare() compare()
rsave()
v1=20 v1=20
v2=-111 v2=-111
c64.STROUT("v1=20, v2=-111\n") c64.STROUT("v1=20, v2=-111\n")
rrestore()
compare() compare()
c64scr.print_byte_decimal(X)
c64.CHROUT('\n')
return
sub compare() { sub compare() {
rsave()
c64.STROUT(" == != < > <= >=\n") c64.STROUT(" == != < > <= >=\n")
rrestore()
if v1==v2 { if v1==v2
rsave()
c64.STROUT(" Q ") c64.STROUT(" Q ")
rrestore() else
} else {
rsave()
c64.STROUT(" . ") c64.STROUT(" . ")
rrestore() if v1!=v2
}
if v1!=v2 {
rsave()
c64.STROUT(" Q ") c64.STROUT(" Q ")
rrestore() else
} else {
rsave()
c64.STROUT(" . ") c64.STROUT(" . ")
rrestore()
}
if v1<v2 { if v1<v2
rsave()
c64.STROUT(" Q ") c64.STROUT(" Q ")
rrestore() else
} else {
rsave()
c64.STROUT(" . ") c64.STROUT(" . ")
rrestore()
}
if v1>v2 { if v1>v2
rsave()
c64.STROUT(" Q ") c64.STROUT(" Q ")
rrestore() else
} else {
rsave()
c64.STROUT(" . ") c64.STROUT(" . ")
rrestore()
}
if v1<=v2 { if v1<=v2
rsave()
c64.STROUT(" Q ") c64.STROUT(" Q ")
rrestore() else
} else {
rsave()
c64.STROUT(" . ") c64.STROUT(" . ")
rrestore()
}
if v1>=v2
if v1>=v2 {
rsave()
c64.STROUT(" Q ") c64.STROUT(" Q ")
rrestore() else
} else {
rsave()
c64.STROUT(" . ") c64.STROUT(" . ")
rrestore()
}
c64.CHROUT('\n') c64.CHROUT('\n')
} }
} }

View File

@ -11,22 +11,10 @@
float v2 float v2
ubyte cr 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: ; check stack usage:
rsave()
c64.STROUT("floating point ") c64.STROUT("floating point ")
rrestore()
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT(' ') c64.CHROUT(' ')
rrestore()
cr=v1==v2 cr=v1==v2
cr=v1==v2 cr=v1==v2
@ -53,123 +41,81 @@
cr=v1>=v2 cr=v1>=v2
cr=v1>=v2 cr=v1>=v2
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
rrestore()
; comparisons: ; comparisons:
rsave()
v1=20 v1=20
v2=666.66 v2=666.66
c64.STROUT("v1=20, v2=666.66\n") c64.STROUT("v1=20, v2=666.66\n")
rrestore()
compare() compare()
rsave()
v1=-20 v1=-20
v2=666.66 v2=666.66
c64.STROUT("v1=-20, v2=666.66\n") c64.STROUT("v1=-20, v2=666.66\n")
rrestore()
compare() compare()
rsave()
v1=666.66 v1=666.66
v2=555.55 v2=555.55
c64.STROUT("v1=666.66, v2=555.55\n") c64.STROUT("v1=666.66, v2=555.55\n")
rrestore()
compare() compare()
rsave()
v1=3.1415 v1=3.1415
v2=-3.1415 v2=-3.1415
c64.STROUT("v1 = 3.1415, v2 = -3.1415\n") c64.STROUT("v1 = 3.1415, v2 = -3.1415\n")
rrestore()
compare() compare()
rsave()
v1=3.1415 v1=3.1415
v2=3.1415 v2=3.1415
c64.STROUT("v1 = v2 = 3.1415\n") c64.STROUT("v1 = v2 = 3.1415\n")
rrestore()
compare() compare()
rsave()
v1=0 v1=0
v2=0 v2=0
c64.STROUT("v1 = v2 = 0\n") c64.STROUT("v1 = v2 = 0\n")
rrestore()
compare() compare()
sub compare() { c64scr.print_byte_decimal(X)
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 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 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()
}
c64.CHROUT('\n') 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 v1<v2
c64.STROUT(" Q ")
else
c64.STROUT(" . ")
if v1>v2
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')
} }
} }
} }

View File

@ -9,19 +9,10 @@
ubyte v2 ubyte v2
ubyte cr ubyte cr
; done:
; ubyte all 6 comparisons
; check stack usage: ; check stack usage:
rsave()
c64.STROUT("unsigned byte ") c64.STROUT("unsigned byte ")
rrestore()
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT(' ') c64.CHROUT(' ')
rrestore()
cr=v1==v2 cr=v1==v2
cr=v1==v2 cr=v1==v2
@ -48,102 +39,62 @@
cr=v1>=v2 cr=v1>=v2
cr=v1>=v2 cr=v1>=v2
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
rrestore()
; comparisons: ; comparisons:
rsave()
v1=20 v1=20
v2=199 v2=199
c64.STROUT("v1=20, v2=199\n") c64.STROUT("v1=20, v2=199\n")
rrestore()
compare() compare()
rsave()
v1=80 v1=80
v2=80 v2=80
c64.STROUT("v1 = v2 = 80\n") c64.STROUT("v1 = v2 = 80\n")
rrestore()
compare() compare()
rsave()
v1=220 v1=220
v2=10 v2=10
c64.STROUT("v1=220, v2=10\n") c64.STROUT("v1=220, v2=10\n")
rrestore()
compare() compare()
c64scr.print_byte_decimal(X)
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 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 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()
}
c64.CHROUT('\n') 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 v1<v2
c64.STROUT(" Q ")
else
c64.STROUT(" . ")
if v1>v2
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')
} }

View File

@ -9,21 +9,10 @@
uword v2 uword v2
ubyte cr ubyte cr
; done:
; ubyte all 6 comparisons
; byte all 6 comparisons
; uword all 6 comparisons
; check stack usage: ; check stack usage:
rsave()
c64.STROUT("unsigned word ") c64.STROUT("unsigned word ")
rrestore()
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT(' ') c64.CHROUT(' ')
rrestore()
cr=v1==v2 cr=v1==v2
cr=v1==v2 cr=v1==v2
@ -50,141 +39,92 @@
cr=v1>=v2 cr=v1>=v2
cr=v1>=v2 cr=v1>=v2
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
rrestore()
; comparisons: ; comparisons:
rsave()
v1=20 v1=20
v2=$00aa v2=$00aa
c64.STROUT("v1=20, v2=$00aa\n") c64.STROUT("v1=20, v2=$00aa\n")
rrestore()
compare() compare()
rsave()
v1=20 v1=20
v2=$ea00 v2=$ea00
c64.STROUT("v1=20, v2=$ea00\n") c64.STROUT("v1=20, v2=$ea00\n")
rrestore()
compare() compare()
rsave()
v1=$c400 v1=$c400
v2=$22 v2=$22
c64.STROUT("v1=$c400, v2=$22\n") c64.STROUT("v1=$c400, v2=$22\n")
rrestore()
compare() compare()
rsave()
v1=$c400 v1=$c400
v2=$2a00 v2=$2a00
c64.STROUT("v1=$c400, v2=$2a00\n") c64.STROUT("v1=$c400, v2=$2a00\n")
rrestore()
compare() compare()
rsave()
v1=$c433 v1=$c433
v2=$2a00 v2=$2a00
c64.STROUT("v1=$c433, v2=$2a00\n") c64.STROUT("v1=$c433, v2=$2a00\n")
rrestore()
compare() compare()
rsave()
v1=$c433 v1=$c433
v2=$2aff v2=$2aff
c64.STROUT("v1=$c433, v2=$2aff\n") c64.STROUT("v1=$c433, v2=$2aff\n")
rrestore()
compare() compare()
rsave()
v1=$aabb v1=$aabb
v2=$aabb v2=$aabb
c64.STROUT("v1 = v2 = aabb\n") c64.STROUT("v1 = v2 = aabb\n")
rrestore()
compare() compare()
rsave()
v1=$aa00 v1=$aa00
v2=$aa00 v2=$aa00
c64.STROUT("v1 = v2 = aa00\n") c64.STROUT("v1 = v2 = aa00\n")
rrestore()
compare() compare()
rsave()
v1=$aa v1=$aa
v2=$aa v2=$aa
c64.STROUT("v1 = v2 = aa\n") c64.STROUT("v1 = v2 = aa\n")
rrestore()
compare() compare()
sub compare() { c64scr.print_byte_decimal(X)
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 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 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()
}
c64.CHROUT('\n') 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 v1<v2
c64.STROUT(" Q ")
else
c64.STROUT(" . ")
if v1>v2
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')
} }

View File

@ -9,22 +9,11 @@
word v2 word v2
ubyte cr ubyte cr
; done:
; ubyte all 6 comparisons
; byte all 6 comparisons
; uword all 6 comparisons
; word all 6 comparisons
; check stack usage: ; check stack usage:
rsave()
c64.STROUT("signed word ") c64.STROUT("signed word ")
rrestore()
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT(' ') c64.CHROUT(' ')
rrestore()
cr=v1==v2 cr=v1==v2
cr=v1==v2 cr=v1==v2
@ -51,191 +40,128 @@
cr=v1>=v2 cr=v1>=v2
cr=v1>=v2 cr=v1>=v2
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
rrestore()
; comparisons: ; comparisons:
rsave()
v1=20 v1=20
v2=$00aa v2=$00aa
c64.STROUT("v1=20, v2=$00aa\n") c64.STROUT("v1=20, v2=$00aa\n")
rrestore()
compare() compare()
rsave()
v1=20 v1=20
v2=$7a00 v2=$7a00
c64.STROUT("v1=20, v2=$7a00\n") c64.STROUT("v1=20, v2=$7a00\n")
rrestore()
compare() compare()
rsave()
v1=$7400 v1=$7400
v2=$22 v2=$22
c64.STROUT("v1=$7400, v2=$22\n") c64.STROUT("v1=$7400, v2=$22\n")
rrestore()
compare() compare()
rsave()
v1=$7400 v1=$7400
v2=$2a00 v2=$2a00
c64.STROUT("v1=$7400, v2=$2a00\n") c64.STROUT("v1=$7400, v2=$2a00\n")
rrestore()
compare() compare()
rsave()
v1=$7433 v1=$7433
v2=$2a00 v2=$2a00
c64.STROUT("v1=$7433, v2=$2a00\n") c64.STROUT("v1=$7433, v2=$2a00\n")
rrestore()
compare() compare()
rsave()
v1=$7433 v1=$7433
v2=$2aff v2=$2aff
c64.STROUT("v1=$7433, v2=$2aff\n") c64.STROUT("v1=$7433, v2=$2aff\n")
rrestore()
compare() compare()
; with negative numbers: ; with negative numbers:
rsave()
v1=-512 v1=-512
v2=$00aa v2=$00aa
c64.STROUT("v1=-512, v2=$00aa\n") c64.STROUT("v1=-512, v2=$00aa\n")
rrestore()
compare() compare()
rsave()
v1=-512 v1=-512
v2=$7a00 v2=$7a00
c64.STROUT("v1=-512, v2=$7a00\n") c64.STROUT("v1=-512, v2=$7a00\n")
rrestore()
compare() compare()
rsave()
v1=$7400 v1=$7400
v2=-512 v2=-512
c64.STROUT("v1=$7400, v2=-512\n") c64.STROUT("v1=$7400, v2=-512\n")
rrestore()
compare() compare()
rsave()
v1=-20000 v1=-20000
v2=-1000 v2=-1000
c64.STROUT("v1=-20000, v2=-1000\n") c64.STROUT("v1=-20000, v2=-1000\n")
rrestore()
compare() compare()
rsave()
v1=-1000 v1=-1000
v2=-20000 v2=-20000
c64.STROUT("v1=-1000, v2=-20000\n") c64.STROUT("v1=-1000, v2=-20000\n")
rrestore()
compare() compare()
rsave()
v1=-1 v1=-1
v2=32767 v2=32767
c64.STROUT("v1=-1, v2=32767\n") c64.STROUT("v1=-1, v2=32767\n")
rrestore()
compare() compare()
rsave()
v1=32767 v1=32767
v2=-1 v2=-1
c64.STROUT("v1=32767, v2=-1\n") c64.STROUT("v1=32767, v2=-1\n")
rrestore()
compare() compare()
rsave()
v1=$7abb v1=$7abb
v2=$7abb v2=$7abb
c64.STROUT("v1 = v2 = 7abb\n") c64.STROUT("v1 = v2 = 7abb\n")
rrestore()
compare() compare()
rsave()
v1=$7a00 v1=$7a00
v2=$7a00 v2=$7a00
c64.STROUT("v1 = v2 = 7a00\n") c64.STROUT("v1 = v2 = 7a00\n")
rrestore()
compare() compare()
rsave()
v1=$aa v1=$aa
v2=$aa v2=$aa
c64.STROUT("v1 = v2 = aa\n") c64.STROUT("v1 = v2 = aa\n")
rrestore()
compare() compare()
sub compare() { c64scr.print_byte_decimal(X)
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 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 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()
}
c64.CHROUT('\n') 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 v1<v2
c64.STROUT(" Q ")
else
c64.STROUT(" . ")
if v1>v2
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')
} }

View File

@ -9,17 +9,15 @@ sub start() {
c64.EXTCOL = 5 c64.EXTCOL = 5
c64.BGCOL0 = 0 c64.BGCOL0 = 0
c64.COLOR = 1 c64.COLOR = 1
c64.VMCSB = %10111 c64.VMCSB |= 2
; use kernel routine to write text (sorry, loops don't work in asm yet) ; use kernel routine to write text
c64.CHROUT('H') c64.STROUT("Hello!\n")
c64.CHROUT('e')
c64.CHROUT('l')
c64.CHROUT('l')
c64.CHROUT('o')
c64.CHROUT('!')
c64.CHROUT('\n')
str question = "How are you?\n"
for ubyte c in 0 to len(question) {
c64.CHROUT(question[c])
}
return return
} }

View File

@ -41,11 +41,9 @@ ask_guess:
c64scr.input_chars(guessstr) c64scr.input_chars(guessstr)
c64.CHROUT('\n') c64.CHROUT('\n')
freadstr_arg = guessstr freadstr_arg = guessstr
rsave()
c64.FREADSTR(Y) c64.FREADSTR(Y)
A, Y = c64flt.GETADRAY() A, Y = c64flt.GETADRAY()
guess=A guess=A
rrestore()
c64.EXTCOL=guess ; @debug c64.EXTCOL=guess ; @debug
c64.BGCOL0=secretnumber ;@debug c64.BGCOL0=secretnumber ;@debug
if(guess==secretnumber) { ; @todo equal_b doesn't work if(guess==secretnumber) { ; @todo equal_b doesn't work

View File

@ -1,28 +1,20 @@
%import c64utils %import c64utils
%import mathlib %import mathlib
%option enable_floats
~ main { ~ main {
sub start() { sub start() {
uword v1 float v1
uword v2 float v2
ubyte cr ubyte cr
; done:
; ubyte all 6 comparisons
; byte all 6 comparisons
; check stack usage: ; check stack usage:
rsave() c64.STROUT("floating point ")
c64.STROUT("unsigned word ")
rrestore()
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT(' ') c64.CHROUT(' ')
rrestore()
cr=v1==v2 cr=v1==v2
cr=v1==v2 cr=v1==v2
@ -49,144 +41,81 @@
cr=v1>=v2 cr=v1>=v2
cr=v1>=v2 cr=v1>=v2
rsave()
c64scr.print_byte_decimal(X) c64scr.print_byte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
rrestore()
; comparisons: ; comparisons:
rsave()
v1=20 v1=20
v2=$00aa v2=666.66
c64.STROUT("v1=20, v2=$00aa\n") c64.STROUT("v1=20, v2=666.66\n")
rrestore()
compare() compare()
rsave() v1=-20
v1=20 v2=666.66
v2=$ea00 c64.STROUT("v1=-20, v2=666.66\n")
c64.STROUT("v1=20, v2=$ea00\n")
rrestore()
compare() compare()
rsave() v1=666.66
v1=$c400 v2=555.55
v2=$22 c64.STROUT("v1=666.66, v2=555.55\n")
c64.STROUT("v1=$c400, v2=$22\n")
rrestore()
compare() compare()
rsave() v1=3.1415
v1=$c400 v2=-3.1415
v2=$2a00 c64.STROUT("v1 = 3.1415, v2 = -3.1415\n")
c64.STROUT("v1=$c400, v2=$2a00\n")
rrestore()
compare() compare()
rsave() v1=3.1415
v1=$c433 v2=3.1415
v2=$2a00 c64.STROUT("v1 = v2 = 3.1415\n")
c64.STROUT("v1=$c433, v2=$2a00\n")
rrestore()
compare() compare()
rsave() v1=0
v1=$c433 v2=0
v2=$2aff c64.STROUT("v1 = v2 = 0\n")
c64.STROUT("v1=$c433, v2=$2aff\n")
rrestore()
compare() compare()
; rsave() c64scr.print_byte_decimal(X)
; 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 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 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()
}
c64.CHROUT('\n') 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 v1<v2
c64.STROUT(" Q ")
else
c64.STROUT(" . ")
if v1>v2
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')
} }
} }
} }

View File

@ -763,10 +763,14 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) { private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
// evaluate the arguments and assign them into the subroutine's argument variables. // 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.asmParameterRegisters.isNotEmpty()) {
if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size) if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size)
throw CompilerException("no support for mix of register and non-register subroutine arguments") 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) // only register arguments (or status-flag bits)
var carryParam: Boolean? = null var carryParam: Boolean? = null
for(arg in arguments.zip(subroutine.asmParameterRegisters)) { for(arg in arguments.zip(subroutine.asmParameterRegisters)) {
@ -783,7 +787,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
translate(assign) translate(assign)
} }
X -> { 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) val assign = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, arg.first, callPosition)
assign.linkParents(arguments[0].parent) assign.linkParents(arguments[0].parent)
translate(assign) translate(assign)
@ -794,7 +801,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
translate(assign) translate(assign)
} }
AX -> { AX -> {
// TODO: save X on stack & restore after call if(!restoreX) {
prog.instr(Opcode.RSAVEX)
restoreX = true
}
val valueA: IExpression val valueA: IExpression
val valueX: IExpression val valueX: IExpression
val paramDt = arg.first.resultingDatatype(namespace, heap) val paramDt = arg.first.resultingDatatype(namespace, heap)
@ -847,7 +857,10 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
} }
XY -> { XY -> {
// TODO: save X on stack & restore after call if(!restoreX) {
prog.instr(Opcode.RSAVEX)
restoreX = true
}
val valueX: IExpression val valueX: IExpression
val valueY: IExpression val valueY: IExpression
val paramDt = arg.first.resultingDatatype(namespace, heap) val paramDt = arg.first.resultingDatatype(namespace, heap)
@ -882,7 +895,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
true -> prog.instr(Opcode.SEC) true -> prog.instr(Opcode.SEC)
false -> prog.instr(Opcode.CLC) false -> prog.instr(Opcode.CLC)
} }
} else { } else {
// only regular (non-register) arguments // only regular (non-register) arguments
for (arg in arguments.zip(subroutine.parameters)) { 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) prog.instr(Opcode.CALL, callLabel = subroutine.scopedname)
if(restoreX)
prog.instr(Opcode.RRESTOREX)
} }
private fun translateBinaryOperator(operator: String, dt: DataType) { private fun translateBinaryOperator(operator: String, dt: DataType) {

View File

@ -219,7 +219,9 @@ enum class Opcode {
SEI, // set irq-disable status flag SEI, // set irq-disable status flag
CLI, // clear irq-disable status flag CLI, // clear irq-disable status flag
RSAVE, // save all internal registers and status flags RSAVE, // save all internal registers and status flags
RSAVEX, // save just X (the evaluation stack pointer)
RRESTORE, // restore all internal registers and status flags RRESTORE, // restore all internal registers and status flags
RRESTOREX, // restore just X (the evaluation stack pointer)
NOP, // do nothing NOP, // do nothing
BREAKPOINT, // breakpoint BREAKPOINT, // breakpoint
TERMINATE, // end the program TERMINATE, // end the program

View File

@ -424,6 +424,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// restore all registers and cpu status flag // restore all registers and cpu status flag
" pla | tay | pla | tax | pla | plp" " 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_BYTE -> " inx"
Opcode.DISCARD_WORD -> " inx" Opcode.DISCARD_WORD -> " inx"
Opcode.DISCARD_FLOAT -> " inx | inx | inx" Opcode.DISCARD_FLOAT -> " inx | inx | inx"

View File

@ -1377,6 +1377,8 @@ class StackVm(private var traceOutputFile: String?) {
P_carry = evalstack.pop().asBooleanValue P_carry = evalstack.pop().asBooleanValue
P_irqd = 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.INLINE_ASSEMBLY -> throw VmExecutionException("stackVm doesn't support executing inline assembly code")
Opcode.PUSH_ADDR_HEAPVAR -> { Opcode.PUSH_ADDR_HEAPVAR -> {
val heapId = variables[ins.callLabel]!!.heapId val heapId = variables[ins.callLabel]!!.heapId

View File

@ -650,6 +650,9 @@ rsave()
Saves the CPU registers and the status flags. Saves the CPU registers and the status flags.
You can now more or less 'safely' use the registers directly, until you You can now more or less 'safely' use the registers directly, until you
restore them again so the generated code can carry on normally. 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() rrestore()
Restores the CPU registers and the status flags from previously saved values. Restores the CPU registers and the status flags from previously saved values.