float.rndseedf() now takes float seed value and is consistent for all CBM compilation targets

This commit is contained in:
Irmen de Jong
2022-11-06 22:41:23 +01:00
parent 207cdaf7a4
commit 5d4bfffc7e
12 changed files with 51 additions and 77 deletions

View File

@@ -57,6 +57,7 @@ romsub $af4e = ABS() clobbers(A,X,Y) ; fac1 = ABS(fac1)
romsub $af51 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive romsub $af51 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
romsub $af54 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than romsub $af54 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
romsub $af57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator romsub $af57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator
romsub $af57 = RND() clobbers(A,X,Y) ; alias for RND_0
romsub $af5a = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2 romsub $af5a = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2
romsub $af5d = ROMUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in current bank in A/Y into fac2 romsub $af5d = ROMUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in current bank in A/Y into fac2
romsub $af60 = MOVFRM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 (use MOVFM instead) romsub $af60 = MOVFRM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 (use MOVFM instead)
@@ -161,21 +162,6 @@ sub rndf() -> float {
}} }}
} }
asmsub rndseedf(ubyte s1 @A, ubyte s2 @X, ubyte s3 @Y) clobbers(X) {
%asm {{
sta _tmpseed
stx _tmpseed+1
sty _tmpseed+2
stx _tmpseed+3
sty _tmpseed+4
lda #<_tmpseed
ldy #>_tmpseed
jsr MOVFM
lda #-1
jmp RND_0
_tmpseed .byte 0,0,0,0,0
}}
}
%asminclude "library:c128/floats.asm" %asminclude "library:c128/floats.asm"
%asminclude "library:c64/floats_funcs.asm" %asminclude "library:c64/floats_funcs.asm"

View File

@@ -182,17 +182,6 @@ sub rndf() -> float {
}} }}
} }
asmsub rndseedf(ubyte s1 @A, ubyte s2 @X, ubyte s3 @Y) clobbers(X) {
%asm {{
pha
tya
ora #128 ; make sure the seed is negative
tay
pla
jsr FREADS24AXY
jmp RND
}}
}
%asminclude "library:c64/floats.asm" %asminclude "library:c64/floats.asm"
%asminclude "library:c64/floats_funcs.asm" %asminclude "library:c64/floats_funcs.asm"

View File

@@ -58,6 +58,7 @@ romsub $fe4e = ABS() clobbers(A,X,Y) ; fac1 = ABS(fac1)
romsub $fe51 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive romsub $fe51 = SIGN() clobbers(X,Y) -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive
romsub $fe54 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than romsub $fe54 = FCOMP(uword mflpt @ AY) clobbers(X,Y) -> ubyte @ A ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than
romsub $fe57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator NOTE: incompatible with C64's RND routine romsub $fe57 = RND_0() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator NOTE: incompatible with C64's RND routine
romsub $fe57 = RND() clobbers(A,X,Y) ; alias for RND_0
romsub $fe5a = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2 romsub $fe5a = CONUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac2
romsub $fe5d = ROMUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in current bank in A/Y into fac2 romsub $fe5d = ROMUPK(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in current bank in A/Y into fac2
romsub $fe60 = MOVFRM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 (use MOVFM instead) romsub $fe60 = MOVFRM(uword mflpt @ AY) clobbers(A,X,Y) ; load mflpt value from memory in A/Y into fac1 (use MOVFM instead)
@@ -160,20 +161,8 @@ sub rndf() -> float {
}} }}
} }
asmsub rndseedf(ubyte s1 @A, ubyte s2 @X, ubyte s3 @Y) clobbers(X) {
%asm {{
sta P8ZP_SCRATCH_REG
lda #0
php
lda P8ZP_SCRATCH_REG
ora #32 ; not sure why this is needed but without it the seed is not consistent
plp ; Z=N=0
jmp floats.RND_0
}}
}
%asminclude "library:c64/floats.asm" %asminclude "library:c64/floats.asm"
%asminclude "library:c64/floats_funcs.asm" %asminclude "library:c64/floats_funcs.asm"
} }

View File

@@ -221,4 +221,20 @@ sub ceil(float value) -> float {
}} }}
} }
sub rndseedf(float seed) {
if seed>0
seed = -seed ; make sure fp seed is always negative
%asm {{
stx floats_store_reg
lda #<seed
ldy #>seed
jsr MOVFM ; load float into fac1
lda #-1
jsr floats.RND
ldx floats_store_reg
rts
}}
}
} }

View File

@@ -131,11 +131,9 @@ sub rndf() -> float {
}} }}
} }
sub rndseedf(ubyte s1, ubyte s2, ubyte s3) { sub rndseedf(float seed) {
%ir {{ %ir {{
loadm.b r65500,floats.rndseedf.s1 loadm.f fr65500,floats.rndseedf.seed
loadm.b r65501,floats.rndseedf.s2
loadm.b r65502,floats.rndseedf.s3
syscall 32 syscall 32
}} }}
} }

View File

@@ -310,7 +310,7 @@ internal class AstChecker(private val program: Program,
} }
else if(param.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) { else if(param.second.registerOrPair in arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD if (param.first.type != DataType.UWORD && param.first.type != DataType.WORD
&& param.first.type != DataType.STR && param.first.type !in ArrayDatatypes && param.first.type != DataType.FLOAT) && param.first.type != DataType.STR && param.first.type !in ArrayDatatypes)
err("parameter '${param.first.name}' should be (u)word (an address) or str") err("parameter '${param.first.name}' should be (u)word (an address) or str")
} }
else if(param.second.statusflag!=null) { else if(param.second.statusflag!=null) {
@@ -325,7 +325,7 @@ internal class AstChecker(private val program: Program,
} }
else if(pair.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) { else if(pair.second.registerOrPair in setOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)) {
if (pair.first != DataType.UWORD && pair.first != DataType.WORD if (pair.first != DataType.UWORD && pair.first != DataType.WORD
&& pair.first != DataType.STR && pair.first !in ArrayDatatypes && pair.first != DataType.FLOAT) && pair.first != DataType.STR && pair.first !in ArrayDatatypes)
err("return type #${index + 1} should be (u)word/address") err("return type #${index + 1} should be (u)word/address")
} }
else if(pair.second.statusflag!=null) { else if(pair.second.statusflag!=null) {

View File

@@ -259,12 +259,8 @@ tan(x)
rndf() rndf()
returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence. returns the next random float between 0.0 and 1.0 from the Pseudo RNG sequence.
rndseedf(ubyte s1, ubyte s2, ubyte s3) rndseedf(seed)
Sets a new seed for the float pseudo-RNG sequence. The seed consists of a three byte value. Sets a new seed for the float pseudo-RNG sequence. Use a negative non-zero number as seed value.
Do not use zeros for the seed!
.. attention::
The rndseedf and maybe the rndf routines may change a bit in the future.
graphics graphics

View File

@@ -648,16 +648,17 @@ the statement body of such a subroutine should consist of just an inline assembl
The ``@ <register>`` part is required for rom and assembly-subroutines, as it specifies for the compiler The ``@ <register>`` part is required for rom and assembly-subroutines, as it specifies for the compiler
what cpu registers should take the routine's arguments. You can use the regular set of registers what cpu registers should take the routine's arguments. You can use the regular set of registers
(A, X, Y), the special 16-bit register pairs to take word values (AX, AY and XY) and even a processor status (A, X, Y), special 16-bit register pairs to take word values (AX, AY and XY) and even a processor status
flag such as Carry (Pc). flag such as Carry (Pc).
It is not possible to use floating point arguments or return values in an asmsub.
.. note:: .. note::
Asmsubs can also be tagged as ``inline asmsub`` to make trivial pieces of assembly inserted Asmsubs can also be tagged as ``inline asmsub`` to make trivial pieces of assembly inserted
directly instead of a call to them. Note that it is literal copy-paste of code that is done, directly instead of a call to them. Note that it is literal copy-paste of code that is done,
so make sure the assembly is actually written to behave like such - which probably means you so make sure the assembly is actually written to behave like such - which probably means you
don't want a ``rts`` or ``jmp`` or ``bra`` in it! don't want a ``rts`` or ``jmp`` or ``bra`` in it!
.. note:: .. note::
The 'virtual' 16-bit registers from the Commander X16 can also be specified as ``R0`` .. ``R15`` . The 'virtual' 16-bit registers from the Commander X16 can also be specified as ``R0`` .. ``R15`` .
This means you don't have to set them up manually before calling a subroutine that takes This means you don't have to set them up manually before calling a subroutine that takes

View File

@@ -3,6 +3,7 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- ir: register allocation per data type a specific allocation, so we are certain when a reg is used it's just for one specific datatype
- ir: write addresses as hex into p8ir file - ir: write addresses as hex into p8ir file
... ...
@@ -19,7 +20,6 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
Compiler: Compiler:
- ir: register allocation per data type a specific allocation, so we are certain when a reg is used it's just for one specific datatype
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code - create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
- ir: mechanism to determine for chunks which registers are getting input values from "outside" - ir: mechanism to determine for chunks which registers are getting input values from "outside"
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk) - ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)

View File

@@ -1,28 +1,27 @@
%import gfx2
%import textio %import textio
%import floats
%zeropage basicsafe %zeropage basicsafe
main { main {
sub start() { sub start() {
gfx2.screen_mode(6) float f1
ubyte pix1 = gfx2.pget(162,120)
gfx2.plot(162,120,7) floats.rndseedf(-1.2345)
ubyte pix2 = gfx2.pget(162,120)
gfx2.plot(162,120,231)
ubyte pix3 = gfx2.pget(162,120)
ubyte pix4 = gfx2.pget(163,120)
ubyte pix5 = gfx2.pget(162,121)
sys.wait(20)
gfx2.screen_mode(0)
txt.print_ub(pix1)
txt.spc() txt.spc()
txt.print_ub(pix2) floats.print_f(floats.rndf())
txt.spc() txt.spc()
txt.print_ub(pix3) floats.print_f(floats.rndf())
txt.spc() txt.spc()
txt.print_ub(pix4) floats.print_f(floats.rndf())
txt.nl()
floats.rndseedf(1.2345)
txt.spc() txt.spc()
txt.print_ub(pix5) floats.print_f(floats.rndf())
txt.spc()
floats.print_f(floats.rndf())
txt.spc()
floats.print_f(floats.rndf())
txt.nl() txt.nl()
} }
} }

View File

@@ -297,10 +297,11 @@ object SysCalls {
vm.registers.setSB(0, 1) vm.registers.setSB(0, 1)
} }
Syscall.RNDFSEED -> { Syscall.RNDFSEED -> {
val seed1 = vm.registers.getUB(SyscallRegisterBase) val seed = vm.registers.getFloat(SyscallRegisterBase)
val seed2 = vm.registers.getUB(SyscallRegisterBase+1) if(seed>0) // always use negative seed, this mimics the behavior on CBM machines
val seed3 = vm.registers.getUB(SyscallRegisterBase+2) vm.randomSeedFloat(-seed)
vm.randomSeedFloat(seed1, seed2, seed3) else
vm.randomSeedFloat(seed)
} }
Syscall.RNDSEED -> { Syscall.RNDSEED -> {
val seed1 = vm.registers.getUW(SyscallRegisterBase) val seed1 = vm.registers.getUW(SyscallRegisterBase)

View File

@@ -2148,9 +2148,8 @@ class VirtualMachine(irProgram: IRProgram) {
randomGenerator = Random(((seed1.toUInt() shl 16) or seed2.toUInt()).toInt()) randomGenerator = Random(((seed1.toUInt() shl 16) or seed2.toUInt()).toInt())
} }
fun randomSeedFloat(seed1: UByte, seed2: UByte, seed3: UByte) { fun randomSeedFloat(seed: Float) {
val seed = (seed1.toUInt() shl 24) or (seed2.toUInt() shl 16) or (seed3.toUInt()) randomGeneratorFloats = Random(seed.toBits())
randomGeneratorFloats = Random(seed.toInt())
} }
} }