diff --git a/compiler/res/prog8lib/c64floats.asm b/compiler/res/prog8lib/c64floats.asm index e13e50354..822b7ac26 100644 --- a/compiler/res/prog8lib/c64floats.asm +++ b/compiler/res/prog8lib/c64floats.asm @@ -8,7 +8,8 @@ ub2float .proc sta P8ZP_SCRATCH_W2 sty P8ZP_SCRATCH_W2+1 ldy P8ZP_SCRATCH_B1 - jsr FREADUY + lda #0 + jsr GIVAYF _fac_to_mem ldx P8ZP_SCRATCH_W2 ldy P8ZP_SCRATCH_W2+1 jsr MOVMF @@ -74,7 +75,8 @@ stack_ub2float .proc lda P8ESTACK_LO,x stx P8ZP_SCRATCH_REG_X tay - jsr FREADUY + lda #0 + jsr GIVAYF jmp push_fac1_as_result .pend @@ -663,8 +665,8 @@ _largest_pos_float .byte 255,127,255,255,255 ; largest positive float .pend func_sum_f .proc - lda #FL_ZERO + lda #ZERO jsr MOVFM jsr prog8_lib.pop_array_and_lengthmin1Y stx P8ZP_SCRATCH_REG_X diff --git a/compiler/res/prog8lib/c64flt.p8 b/compiler/res/prog8lib/c64flt.p8 index bce969932..83f9ee453 100644 --- a/compiler/res/prog8lib/c64flt.p8 +++ b/compiler/res/prog8lib/c64flt.p8 @@ -6,12 +6,12 @@ %option enable_floats - c64flt { ; ---- this block contains C-64 floating point related functions ---- const float PI = 3.141592653589793 const float TWOPI = 6.283185307179586 + const float ZERO = 0.0 ; ---- C64 basic and kernal ROM float constants and functions ---- @@ -35,13 +35,11 @@ c64flt { &float FL_TWOPI = $e2e5 ; 2 * PI &float FL_FR4 = $e2ea ; .25 ; oddly enough, 0.0 isn't available in the kernel. - float FL_ZERO = 0.0 ; oddly enough 0.0 isn't available in the kernel ; note: fac1/2 might get clobbered even if not mentioned in the function's name. ; note: for subtraction and division, the left operand is in fac2, the right operand in fac1. -; checked functions below: romsub $bba2 = MOVFM(uword mflpt @ AY) clobbers(A,Y) ; load mflpt value from memory in A/Y into fac1 romsub $bba6 = FREADMEM() clobbers(A,Y) ; load mflpt value from memory in $22/$23 into fac1 romsub $ba8c = CONUPK(uword mflpt @ AY) clobbers(A,Y) ; load mflpt value from memory in A/Y into fac2 @@ -91,6 +89,7 @@ romsub $bb12 = FDIVT() clobbers(A,X,Y) ; fac1 = fac2/fac1 romsub $bb0f = FDIV(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 = mflpt in A/Y / fac1 (remainder in fac2) romsub $bf7b = FPWRT() clobbers(A,X,Y) ; fac1 = fac2 ** fac1 romsub $bf78 = FPWR(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 = fac2 ** mflpt from A/Y +romsub $bd7e = FINLOG(byte value @A) clobbers (A, X, Y) ; fac1 += signed byte in A romsub $aed4 = NOTOP() clobbers(A,X,Y) ; fac1 = NOT(fac1) romsub $bccc = INT() clobbers(A,X,Y) ; INT() truncates, use FADDH first to round instead of trunc @@ -193,33 +192,26 @@ asmsub GETADRAY () clobbers(X) -> uword @ AY { } sub print_f (float value) { - ; ---- prints the floating point value (without a newline) using basic rom routines. + ; ---- prints the floating point value (without a newline). %asm {{ stx P8ZP_SCRATCH_REG_X lda #value jsr MOVFM ; load float into fac1 jsr FOUT ; fac1 to string in A/Y - jsr c64.STROUT ; print string in A/Y + sta P8ZP_SCRATCH_B1 + sty P8ZP_SCRATCH_REG + ldy #0 +- lda (P8ZP_SCRATCH_B1),y + beq + + jsr c64.CHROUT + iny + bne - ldx P8ZP_SCRATCH_REG_X - rts ++ rts }} } -sub print_fln (float value) { - ; ---- prints the floating point value (with a newline at the end) using basic rom routines - %asm {{ - stx P8ZP_SCRATCH_REG_X - lda #value - jsr MOVFM ; load float into fac1 - jsr FPRINTLN ; print fac1 with newline - ldx P8ZP_SCRATCH_REG_X - rts - }} - -} - %asminclude "library:c64floats.asm", "" -} ; ------ end of block c64flt +} diff --git a/compiler/res/prog8lib/cx16flt.p8 b/compiler/res/prog8lib/cx16flt.p8 new file mode 100644 index 000000000..f29dab1e4 --- /dev/null +++ b/compiler/res/prog8lib/cx16flt.p8 @@ -0,0 +1,140 @@ +; Prog8 definitions for floating point handling on the CommanderX16 +; +; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 +; +; indent format: TABS, size=8 + +%option enable_floats + +c64flt { + ; ---- this block contains C-64 floating point related functions ---- + + const float PI = 3.141592653589793 + const float TWOPI = 6.283185307179586 + const float ZERO = 0.0 + + +; ---- ROM float functions ---- + + ; note: the fac1 and fac2 are working registers and take 6 bytes each, + ; floats in memory (and rom) are stored in 5-byte MFLPT packed format. + +; note: fac1/2 might get clobbered even if not mentioned in the function's name. +; note: for subtraction and division, the left operand is in fac2, the right operand in fac1. + +romsub $fe00 = AYINT() clobbers(A,X,Y) ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) + +; GIVAYF: signed word in Y/A (note different lsb/msb order) -> float in fac1 +; there is also c64flt.GIVUAYFAY - unsigned word in A/Y (lo/hi) to fac1 +; (tip: use GIVAYFAY to use A/Y input; lo/hi switched to normal order) +romsub $fe03 = GIVAYF(ubyte lo @ Y, ubyte hi @ A) clobbers(A,X,Y) + +; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15) +; (tip: use GETADRAY to get A/Y output; lo/hi switched to normal little endian order) +romsub $fe06 = GETADR() clobbers(X) -> ubyte @ Y, ubyte @ A + +romsub $fe09 = FADDH() clobbers(A,X,Y) ; fac1 += 0.5, for rounding- call this before INT +romsub $fe0c = FSUB(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 = mflpt from A/Y - fac1 +romsub $fe0f = FSUBT() clobbers(A,X,Y) ; fac1 = fac2-fac1 mind the order of the operands +romsub $fe12 = FADD(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 += mflpt value from A/Y +romsub $fe15 = FADDT() clobbers(A,X,Y) ; fac1 += fac2 +romsub $fe1b = ZEROFC() clobbers(A,X,Y) ; fac1 = 0 +romsub $fe1e = NORMAL() clobbers(A,X,Y) ; normalize fac1 (?) +romsub $fe24 = LOG() clobbers(A,X,Y) ; fac1 = LN(fac1) (natural log) +romsub $fe27 = FMULT(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 *= mflpt value from A/Y +romsub $fe2a = FMULTT() clobbers(A,X,Y) ; fac1 *= fac2 +romsub $fe33 = CONUPK(uword mflpt @ AY) clobbers(A,Y) ; load mflpt value from memory in A/Y into fac2 +romsub $fe36 = MUL10() clobbers(A,X,Y) ; fac1 *= 10 +romsub $fe3c = DIV10() clobbers(A,X,Y) ; fac1 /= 10 , CAUTION: result is always positive! +romsub $fe3f = FDIV(uword mflpt @ AY) clobbers(A,X,Y) ; fac1 = mflpt in A/Y / fac1 (remainder in fac2) +romsub $fe42 = FDIVT() clobbers(A,X,Y) ; fac1 = fac2/fac1 (remainder in fac2) mind the order of the operands + +romsub $fe48 = MOVFM(uword mflpt @ AY) clobbers(A,Y) ; load mflpt value from memory in A/Y into fac1 +romsub $fe4b = MOVMF(uword mflpt @ XY) clobbers(A,Y) ; store fac1 to memory X/Y as 5-byte mflpt +romsub $fe4e = MOVFA() clobbers(A,X) ; copy fac2 to fac1 +romsub $fe51 = MOVAF() clobbers(A,X) ; copy fac1 to fac2 (rounded) +romsub $fe54 = MOVEF() clobbers(A,X) ; copy fac1 to fac2 +romsub $fe5a = SIGN() -> ubyte @ A ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive +romsub $fe5d = SGN() clobbers(A,X,Y) ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) +romsub $fe60 = FREADSA(byte value @ A) clobbers(A,X,Y) ; 8 bit signed A -> float in fac1 +romsub $fe6c = ABS() ; fac1 = ABS(fac1) +romsub $fe6f = 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 $fe78 = INT() clobbers(A,X,Y) ; INT() truncates, use FADDH first to round instead of trunc +romsub $fe7e = FINLOG(byte value @A) clobbers (A, X, Y) ; fac1 += signed byte in A +romsub $fe81 = FOUT() clobbers(X) -> uword @ AY ; fac1 -> string, address returned in AY ($0100) +romsub $fe8a = SQR() clobbers(A,X,Y) ; fac1 = SQRT(fac1) +romsub $fe8d = FPWRT() clobbers(A,X,Y) ; fac1 = fac2 ** fac1 +romsub $fe93 = NEGOP() clobbers(A) ; switch the sign of fac1 +romsub $fe96 = EXP() clobbers(A,X,Y) ; fac1 = EXP(fac1) (e ** fac1) +romsub $fe9f = RND2(byte value @A) clobbers(A,X,Y) ; fac1 = RND(A) float random number generator +romsub $fea2 = RND() clobbers(A,X,Y) ; fac1 = RND(fac1) float random number generator +romsub $fea5 = COS() clobbers(A,X,Y) ; fac1 = COS(fac1) +romsub $fea8 = SIN() clobbers(A,X,Y) ; fac1 = SIN(fac1) +romsub $feab = TAN() clobbers(A,X,Y) ; fac1 = TAN(fac1) +romsub $feae = ATN() clobbers(A,X,Y) ; fac1 = ATN(fac1) + + +asmsub GIVUAYFAY (uword value @ AY) clobbers(A,X,Y) { + ; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1 + %asm {{ + jmp GIVAYFAY ; TODO make this work for unsigned!! + }} +} + + +asmsub GIVAYFAY (uword value @ AY) clobbers(A,X,Y) { + ; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1 + %asm {{ + sta P8ZP_SCRATCH_REG + tya + ldy P8ZP_SCRATCH_REG + jmp GIVAYF ; this uses the inverse order, Y/A + }} +} + +asmsub FTOSWRDAY () clobbers(X) -> uword @ AY { + ; ---- fac1 to signed word in A/Y + %asm {{ + jsr FTOSWORDYA ; note the inverse Y/A order + sta P8ZP_SCRATCH_REG + tya + ldy P8ZP_SCRATCH_REG + rts + }} +} + +asmsub GETADRAY () clobbers(X) -> uword @ AY { + ; ---- fac1 to unsigned word in A/Y + %asm {{ + jsr GETADR ; this uses the inverse order, Y/A + sta P8ZP_SCRATCH_B1 + tya + ldy P8ZP_SCRATCH_B1 + rts + }} +} + +sub print_f (float value) { + ; ---- prints the floating point value (without a newline). + %asm {{ + stx P8ZP_SCRATCH_REG_X + lda #value + jsr MOVFM ; load float into fac1 + jsr FOUT ; fac1 to string in A/Y + sta P8ZP_SCRATCH_B1 + sty P8ZP_SCRATCH_REG + ldy #0 +- lda (P8ZP_SCRATCH_B1),y + beq + + jsr c64.CHROUT + iny + bne - + ldx P8ZP_SCRATCH_REG_X ++ rts + }} +} + +%asminclude "library:c64floats.asm", "" + +} diff --git a/compiler/res/prog8lib/cx16textio.p8 b/compiler/res/prog8lib/cx16textio.p8 index b2628275c..f32084d5e 100644 --- a/compiler/res/prog8lib/cx16textio.p8 +++ b/compiler/res/prog8lib/cx16textio.p8 @@ -11,7 +11,7 @@ txt { -asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { +asmsub clear_screen (ubyte char @ A, ubyte txtcolor @ Y) clobbers(A) { ; ---- clear the character screen with the given fill character and character color. %asm {{ @@ -224,6 +224,32 @@ asmsub print_w (word value @ AY) clobbers(A,Y) { }} } +ubyte[16] color_to_charcode = [$90,$05,$1c,$9f,$9c,$1e,$1f,$9e,$81,$95,$96,$97,$98,$99,$9a,$9b] + +sub color (ubyte txtcol) { + c64.CHROUT(color_to_charcode[txtcol & 15]) +} + +sub color2 (ubyte txtcol, ubyte bgcol) { + c64.CHROUT(color_to_charcode[bgcol & 15]) + c64.CHROUT(1) ; switch fg and bg colors + c64.CHROUT(color_to_charcode[txtcol & 15]) +} + +sub setc (ubyte column, ubyte row, ubyte char) { + ; ---- set char at the given position on the screen + %asm {{ + phx + ldy column + ldx row + clc + jsr c64.PLOT + plx + lda char + jmp c64.CHROUT + }} +} + asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) { ; ---- safe wrapper around PLOT kernel routine, to save the X register. %asm {{ diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt index 7bce66478..983d14106 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt @@ -151,7 +151,8 @@ private fun optimizeSameAssignments(linesByFourteen: List