From e67e4c0b134e6cbebd54855e26e50f5c89681bf8 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 30 Dec 2017 21:36:42 +0100 Subject: [PATCH] allow just ? in sub return spec --- il65/codegen.py | 9 +- il65/parse.py | 9 +- lib/c64lib.ill | 192 ++++++++++++++++++------------------ lib/mathlib.ill | 2 +- reference.md | 2 + testsource/conditionals.ill | 12 +-- testsource/floats.ill | 2 +- testsource/numbergame.ill | 1 + todo.ill | 20 +--- 9 files changed, 123 insertions(+), 126 deletions(-) diff --git a/il65/codegen.py b/il65/codegen.py index aaf27157a..ab0634f99 100644 --- a/il65/codegen.py +++ b/il65/codegen.py @@ -729,8 +729,13 @@ class CodeGenerator: if isinstance(cv, ParseResult.RegisterValue): branch = "bne" if stmt.condition.ifstatus == "true" else "beq" self.p("\t\tsta " + Parser.to_hex(Zeropage.SCRATCH_B1)) # need to save A, because the goto may not be taken - if cv.register in REGISTER_BYTES: - self.p("\t\tst{:s} *+2\t; self-modify".format(cv.register.lower())) + if cv.register == 'Y': + self.p("\t\tlda ($00),y") + elif cv.register == 'X': + self.p("\t\tstx *+2\t; self-modify") + self.p("\t\tlda $ff") + elif cv.register == 'A': + self.p("\t\tsta *+2\t; self-modify") self.p("\t\tlda $ff") else: self.p("\t\tst{:s} (+)+1\t; self-modify".format(cv.register[0].lower())) diff --git a/il65/parse.py b/il65/parse.py index 952f6b820..4841e64e6 100644 --- a/il65/parse.py +++ b/il65/parse.py @@ -1103,6 +1103,12 @@ class Parser: if len(all_paramnames) != len(set(all_paramnames)): raise self.PError("duplicates in parameter names") results = [m.group("name") for m in re.finditer(r"\s*(?P(?:\w+)\??)\s*(?:,|$)", resultlist)] + if not results: + if resultlist == "?": + # a single '?' in the result spec means: all 3 registers clobbered + results = ['A?', 'X?', 'Y?'] + elif resultlist: + raise self.PError("invalid return values spec") subroutine_block = None if code_decl: address = None @@ -1252,8 +1258,7 @@ class Parser: raise self.PError("invalid call target (should contain 16-bit)") else: target = self.parse_expression(targetstr) - if not isinstance(target, (ParseResult.IntegerValue, ParseResult.RegisterValue, - ParseResult.MemMappedValue, ParseResult.IndirectValue)): + if not isinstance(target, (ParseResult.IntegerValue, ParseResult.MemMappedValue, ParseResult.IndirectValue)): raise self.PError("cannot call that type of symbol") if isinstance(target, ParseResult.IndirectValue) \ and not isinstance(target.value, (ParseResult.IntegerValue, ParseResult.RegisterValue, ParseResult.MemMappedValue)): diff --git a/lib/c64lib.ill b/lib/c64lib.ill index aaf28c256..ea1eaaa3c 100644 --- a/lib/c64lib.ill +++ b/lib/c64lib.ill @@ -98,69 +98,69 @@ output raw ; note: for subtraction and division, the left operand is in fac2, the right operand in fac1. ; checked functions below: -sub MOVFM (mflpt: AY) -> (A?, Y?) = $bba2 ; load mflpt value from memory in A/Y into fac1 -sub FREADMEM () -> (A?, Y?) = $bba6 ; load mflpt value from memory in $22/$23 into fac1 -sub CONUPK (mflpt: AY) -> (A?, Y?) = $ba8c ; load mflpt value from memory in A/Y into fac2 -sub FAREADMEM () -> (A?, Y?) = $ba90 ; load mflpt value from memory in $22/$23 into fac2 -sub MOVFA () -> (A?, X?) = $bbfc ; copy fac2 to fac1 -sub MOVAF () -> (A?, X?) = $bc0c ; copy fac1 to fac2 (rounded) -sub MOVEF () -> (A?, X?) = $bc0f ; copy fac1 to fac2 -sub FTOMEMXY (mflpt: XY) -> (A?, Y?) = $bbd4 ; store fac1 to memory X/Y as 5-byte mflpt -sub FTOSWORDYA () -> (Y, A, X?) = $b1aa ; fac1-> signed word in Y/A (might throw ILLEGAL QUANTITY) +sub MOVFM (mflpt: AY) -> (A?, Y?) = $bba2 ; load mflpt value from memory in A/Y into fac1 +sub FREADMEM () -> (A?, Y?) = $bba6 ; load mflpt value from memory in $22/$23 into fac1 +sub CONUPK (mflpt: AY) -> (A?, Y?) = $ba8c ; load mflpt value from memory in A/Y into fac2 +sub FAREADMEM () -> (A?, Y?) = $ba90 ; load mflpt value from memory in $22/$23 into fac2 +sub MOVFA () -> (A?, X?) = $bbfc ; copy fac2 to fac1 +sub MOVAF () -> (A?, X?) = $bc0c ; copy fac1 to fac2 (rounded) +sub MOVEF () -> (A?, X?) = $bc0f ; copy fac1 to fac2 +sub FTOMEMXY (mflpt: XY) -> (A?, Y?) = $bbd4 ; store fac1 to memory X/Y as 5-byte mflpt +sub FTOSWORDYA () -> (Y, A, X?) = $b1aa ; fac1-> signed word in Y/A (might throw ILLEGAL QUANTITY) ; use c64util.FTOSWRDAY to get A/Y output (lo/hi switched to normal order) -sub GETADR () -> (Y, A, X?) = $b7f7 ; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) +sub GETADR () -> (Y, A, X?) = $b7f7 ; fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) ; (result also in $14/15) use c64util.GETADRAY to get A/Y output (lo/hi switched to normal order) -sub QINT () -> (A?, X?, Y?) = $bc9b ; fac1 -> 4-byte signed integer in 98-101 ($62-$65), with the MSB FIRST. -sub AYINT () -> (A?, X?, Y?) = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) -sub GIVAYF (lo: Y, hi: A) -> (A?, X?, Y?) = $b391 ; signed word in Y/A -> float in fac1 +sub QINT () -> (?) = $bc9b ; fac1 -> 4-byte signed integer in 98-101 ($62-$65), with the MSB FIRST. +sub AYINT () -> (?) = $b1bf ; fac1-> signed word in 100-101 ($64-$65) MSB FIRST. (might throw ILLEGAL QUANTITY) +sub GIVAYF (lo: Y, hi: A) -> (?) = $b391 ; signed word in Y/A -> float in fac1 ; use c64util.GIVAYFAY to use A/Y input (lo/hi switched to normal order) ; there is also c64util.GIVUAYF - unsigned word in A/Y (lo/hi) to fac1 ; there is also c64util.FREADS32 that reads from 98-101 ($62-$65) MSB FIRST ; there is also c64util.FREADUS32 that reads from 98-101 ($62-$65) MSB FIRST ; there is also c64util.FREADS24AXY that reads signed int24 into fac1 from A/X/Y (lo/mid/hi bytes) -sub FREADUY (ubyte: Y) -> (A?, X?, Y?) = $b3a2 ; 8 bit unsigned Y -> float in fac1 -sub FREADSA (sbyte: A) -> (A?, X?, Y?) = $bc3c ; 8 bit signed A -> float in fac1 -sub FREADSTR (len: A) -> (A?, X?, Y?) = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length -sub FPRINTLN () -> (A?, X?, Y?) = $aabc ; print string of fac1, on one line (= with newline) -sub FOUT () -> (AY, X?) = $bddd ; fac1 -> string, address returned in AY ($0100) +sub FREADUY (ubyte: Y) -> (?) = $b3a2 ; 8 bit unsigned Y -> float in fac1 +sub FREADSA (sbyte: A) -> (?) = $bc3c ; 8 bit signed A -> float in fac1 +sub FREADSTR (len: A) -> (?) = $b7b5 ; str -> fac1, $22/23 must point to string, A=string length +sub FPRINTLN () -> (?) = $aabc ; print string of fac1, on one line (= with newline) +sub FOUT () -> (AY, X?) = $bddd ; fac1 -> string, address returned in AY ($0100) -sub FADDH () -> (A?, X?, Y?) = $b849 ; fac1 += 0.5, for rounding- call this before INT -sub MUL10 () -> (A?, X?, Y?) = $bae2 ; fac1 *= 10 -sub DIV10 () -> (A?, X?, Y?) = $bafe ; fac1 /= 10 , CAUTION: result is always positive! +sub FADDH () -> (?) = $b849 ; fac1 += 0.5, for rounding- call this before INT +sub MUL10 () -> (?) = $bae2 ; fac1 *= 10 +sub DIV10 () -> (?) = $bafe ; fac1 /= 10 , CAUTION: result is always positive! sub FCOMP (mflpt: AY) -> (A, X?, Y?) = $bc5b ; A = compare fac1 to mflpt in A/Y, 0=equal 1=fac1 is greater, 255=fac1 is less than -sub FADDT () -> (A?, X?, Y?) = $b86a ; fac1 += fac2 -sub FADD (mflpt: AY) -> (A?, X?, Y?) = $b867 ; fac1 += mflpt value from A/Y -sub FSUBT () -> (A?, X?, Y?) = $b853 ; fac1 = fac2-fac1 mind the order of the operands -sub FSUB (mflpt: AY) -> (A?, X?, Y?) = $b850 ; fac1 = mflpt from A/Y - fac1 -sub FMULTT () -> (A?, X?, Y?) = $ba2b ; fac1 *= fac2 -sub FMULT (mflpt: AY) -> (A?, X?, Y?) = $ba28 ; fac1 *= mflpt value from A/Y -sub FDIVT () -> (A?, X?, Y?) = $bb12 ; fac1 = fac2/fac1 mind the order of the operands -sub FDIV (mflpt: AY) -> (A?, X?, Y?) = $bb0f ; fac1 = mflpt in A/Y / fac1 -sub FPWRT () -> (A?, X?, Y?) = $bf7b ; fac1 = fac2 ** fac1 -sub FPWR (mflpt: AY) -> (A?, X?, Y?) = $bf78 ; fac1 = fac2 ** mflpt from A/Y +sub FADDT () -> (?) = $b86a ; fac1 += fac2 +sub FADD (mflpt: AY) -> (?) = $b867 ; fac1 += mflpt value from A/Y +sub FSUBT () -> (?) = $b853 ; fac1 = fac2-fac1 mind the order of the operands +sub FSUB (mflpt: AY) -> (?) = $b850 ; fac1 = mflpt from A/Y - fac1 +sub FMULTT () -> (?) = $ba2b ; fac1 *= fac2 +sub FMULT (mflpt: AY) -> (?) = $ba28 ; fac1 *= mflpt value from A/Y +sub FDIVT () -> (?) = $bb12 ; fac1 = fac2/fac1 mind the order of the operands +sub FDIV (mflpt: AY) -> (?) = $bb0f ; fac1 = mflpt in A/Y / fac1 +sub FPWRT () -> (?) = $bf7b ; fac1 = fac2 ** fac1 +sub FPWR (mflpt: AY) -> (?) = $bf78 ; fac1 = fac2 ** mflpt from A/Y -sub NOTOP () -> (A?, X?, Y?) = $aed4 ; fac1 = NOT(fac1) -sub INT () -> (A?, X?, Y?) = $bccc ; INT() truncates, use FADDH first to round instead of trunc -sub LOG () -> (A?, X?, Y?) = $b9ea ; fac1 = LN(fac1) (natural log) -sub SGN () -> (A?, X?, Y?) = $bc39 ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) -sub SIGN () -> (A) = $bc2b ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive -sub ABS () -> () = $bc58 ; fac1 = ABS(fac1) -sub SQR () -> (A?, X?, Y?) = $bf71 ; fac1 = SQRT(fac1) -sub EXP () -> (A?, X?, Y?) = $bfed ; fac1 = EXP(fac1) (e ** fac1) -sub NEGOP () -> (A?) = $bfb4 ; switch the sign of fac1 -sub RND () -> (A?, X?, Y?) = $e097 ; fac1 = RND() (use RNDA instead) -sub RNDA (A) -> (A?, X?, Y?) = $e09a ; fac1 = RND(A) -sub COS () -> (A?, X?, Y?) = $e264 ; fac1 = COS(fac1) -sub SIN () -> (A?, X?, Y?) = $e26b ; fac1 = SIN(fac1) -sub TAN () -> (A?, X?, Y?) = $e2b4 ; fac1 = TAN(fac1) -sub ATN () -> (A?, X?, Y?) = $e30e ; fac1 = ATN(fac1) +sub NOTOP () -> (?) = $aed4 ; fac1 = NOT(fac1) +sub INT () -> (?) = $bccc ; INT() truncates, use FADDH first to round instead of trunc +sub LOG () -> (?) = $b9ea ; fac1 = LN(fac1) (natural log) +sub SGN () -> (?) = $bc39 ; fac1 = SGN(fac1), result of SIGN (-1, 0 or 1) +sub SIGN () -> (A) = $bc2b ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive +sub ABS () -> () = $bc58 ; fac1 = ABS(fac1) +sub SQR () -> (?) = $bf71 ; fac1 = SQRT(fac1) +sub EXP () -> (?) = $bfed ; fac1 = EXP(fac1) (e ** fac1) +sub NEGOP () -> (A?) = $bfb4 ; switch the sign of fac1 +sub RND () -> (?) = $e097 ; fac1 = RND() (use RNDA instead) +sub RNDA (A) -> (?) = $e09a ; fac1 = RND(A) +sub COS () -> (?) = $e264 ; fac1 = COS(fac1) +sub SIN () -> (?) = $e26b ; fac1 = SIN(fac1) +sub TAN () -> (?) = $e2b4 ; fac1 = TAN(fac1) +sub ATN () -> (?) = $e30e ; fac1 = ATN(fac1) ; ---- C64 basic routines ---- -sub CLEARSCR () -> (A?, X?, Y?) = $E544 ; clear the screen -sub HOMECRSR () -> (A?, X?, Y?) = $E566 ; cursor to top left of screen +sub CLEARSCR () -> (?) = $E544 ; clear the screen +sub HOMECRSR () -> (?) = $E566 ; cursor to top left of screen ; ---- end of C64 basic routines ---- @@ -169,47 +169,47 @@ sub HOMECRSR () -> (A?, X?, Y?) = $E566 ; cursor to top left of screen ; ---- C64 kernal routines ---- -sub IRQDFRT () -> (A?, X?, Y?) = $EA31 ; default IRQ routine -sub IRQDFEND () -> (A?, X?, Y?) = $EA81 ; default IRQ end/cleanup -sub CINT () -> (A?, X?, Y?) = $FF81 ; (alias: SCINIT) initialize screen editor and video chip -sub IOINIT () -> (A?, X?) = $FF84 ; initialize I/O devices (CIA, SID, IRQ) -sub RAMTAS () -> (A?, X?, Y?) = $FF87 ; initialize RAM, tape buffer, screen -sub RESTOR () -> (A?, X?, Y?) = $FF8A ; restore default I/O vectors +sub IRQDFRT () -> (?) = $EA31 ; default IRQ routine +sub IRQDFEND () -> (?) = $EA81 ; default IRQ end/cleanup +sub CINT () -> (?) = $FF81 ; (alias: SCINIT) initialize screen editor and video chip +sub IOINIT () -> (A?, X?) = $FF84 ; initialize I/O devices (CIA, SID, IRQ) +sub RAMTAS () -> (?) = $FF87 ; initialize RAM, tape buffer, screen +sub RESTOR () -> (?) = $FF8A ; restore default I/O vectors sub VECTOR (dir: SC, userptr: XY) -> (A?, Y?) = $FF8D ; read/set I/O vector table -sub SETMSG (value: A) -> () = $FF90 ; set Kernal message control flag -sub SECOND (address: A) -> (A?) = $FF93 ; (alias: LSTNSA) send secondary address after LISTEN -sub TKSA (address: A) -> (A?) = $FF96 ; (alias: TALKSA) send secondary address after TALK -sub MEMTOP (dir: SC, address: XY) -> (XY) = $FF99 ; read/set top of memory pointer -sub MEMBOT (dir: SC, address: XY) -> (XY) = $FF9C ; read/set bottom of memory pointer -sub SCNKEY () -> (A?, X?, Y?) = $FF9F ; scan the keyboard -sub SETTMO (timeout: A) -> () = $FFA2 ; set time-out flag for IEEE bus -sub ACPTR () -> (A) = $FFA5 ; (alias: IECIN) input byte from serial bus -sub CIOUT (byte: A) -> () = $FFA8 ; (alias: IECOUT) output byte to serial bus -sub UNTLK () -> (A?) = $FFAB ; command serial bus device to UNTALK -sub UNLSN () -> (A?) = $FFAE ; command serial bus device to UNLISTEN -sub LISTEN (device: A) -> (A?) = $FFB1 ; command serial bus device to LISTEN -sub TALK (device: A) -> (A?) = $FFB4 ; command serial bus device to TALK -sub READST () -> (A) = $FFB7 ; read I/O status word +sub SETMSG (value: A) -> () = $FF90 ; set Kernal message control flag +sub SECOND (address: A) -> (A?) = $FF93 ; (alias: LSTNSA) send secondary address after LISTEN +sub TKSA (address: A) -> (A?) = $FF96 ; (alias: TALKSA) send secondary address after TALK +sub MEMTOP (dir: SC, address: XY) -> (XY) = $FF99 ; read/set top of memory pointer +sub MEMBOT (dir: SC, address: XY) -> (XY) = $FF9C ; read/set bottom of memory pointer +sub SCNKEY () -> (?) = $FF9F ; scan the keyboard +sub SETTMO (timeout: A) -> () = $FFA2 ; set time-out flag for IEEE bus +sub ACPTR () -> (A) = $FFA5 ; (alias: IECIN) input byte from serial bus +sub CIOUT (byte: A) -> () = $FFA8 ; (alias: IECOUT) output byte to serial bus +sub UNTLK () -> (A?) = $FFAB ; command serial bus device to UNTALK +sub UNLSN () -> (A?) = $FFAE ; command serial bus device to UNLISTEN +sub LISTEN (device: A) -> (A?) = $FFB1 ; command serial bus device to LISTEN +sub TALK (device: A) -> (A?) = $FFB4 ; command serial bus device to TALK +sub READST () -> (A) = $FFB7 ; read I/O status word sub SETLFS (logical: A, device: X, address: Y) -> () = $FFBA ; set logical file parameters sub SETNAM (namelen: A, filename: XY) -> () = $FFBD ; set filename parameters -sub OPEN () -> (A?, X?, Y?) = $FFC0 ; (via 794 ($31A)) open a logical file -sub CLOSE (logical: A) -> (A?, X?, Y?) = $FFC3 ; (via 796 ($31C)) close a logical file -sub CHKIN (logical: X) -> (A?, X?) = $FFC6 ; (via 798 ($31E)) define an input channel -sub CHKOUT (logical: X) -> (A?, X?) = $FFC9 ; (via 800 ($320)) define an output channel -sub CLRCHN () -> (A?, X?) = $FFCC ; (via 802 ($322)) restore default devices -sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read. -sub CHROUT (char: A) -> () = $FFD2 ; (via 806 ($326)) output a character +sub OPEN () -> (?) = $FFC0 ; (via 794 ($31A)) open a logical file +sub CLOSE (logical: A) -> (?) = $FFC3 ; (via 796 ($31C)) close a logical file +sub CHKIN (logical: X) -> (A?, X?) = $FFC6 ; (via 798 ($31E)) define an input channel +sub CHKOUT (logical: X) -> (A?, X?) = $FFC9 ; (via 800 ($320)) define an output channel +sub CLRCHN () -> (A?, X?) = $FFCC ; (via 802 ($322)) restore default devices +sub CHRIN () -> (A, Y?) = $FFCF ; (via 804 ($324)) input a character (for keyboard, read a whole line from the screen) A=byte read. +sub CHROUT (char: A) -> () = $FFD2 ; (via 806 ($326)) output a character sub LOAD (verify: A, address: XY) -> (SC, A, X, Y) = $FFD5 ; (via 816 ($330)) load from device sub SAVE (zp_startaddr: A, endaddr: XY) -> (SC, A) = $FFD8 ; (via 818 ($332)) save to a device sub SETTIM (low: A, middle: X, high: Y) -> () = $FFDB ; set the software clock -sub RDTIM () -> (A, X, Y) = $FFDE ; read the software clock -sub STOP () -> (SZ, SC, A?, X?) = $FFE1 ; (via 808 ($328)) check the STOP key -sub GETIN () -> (A, X?, Y?) = $FFE4 ; (via 810 ($32A)) get a character -sub CLALL () -> (A?, X?) = $FFE7 ; (via 812 ($32C)) close all files -sub UDTIM () -> (A?, X?) = $FFEA ; update the software clock -sub SCREEN () -> (X, Y) = $FFED ; read number of screen rows and columns +sub RDTIM () -> (A, X, Y) = $FFDE ; read the software clock +sub STOP () -> (SZ, SC, A?, X?) = $FFE1 ; (via 808 ($328)) check the STOP key +sub GETIN () -> (A, X?, Y?) = $FFE4 ; (via 810 ($32A)) get a character +sub CLALL () -> (A?, X?) = $FFE7 ; (via 812 ($32C)) close all files +sub UDTIM () -> (A?, X?) = $FFEA ; update the software clock +sub SCREEN () -> (X, Y) = $FFED ; read number of screen rows and columns sub PLOT (dir: SC, col: X, row: Y) -> (X, Y) = $FFF0 ; read/set position of cursor on screen -sub IOBASE () -> (X, Y) = $FFF3 ; read base address of I/O devices +sub IOBASE () -> (X, Y) = $FFF3 ; read base address of I/O devices ; ---- end of C64 kernal routines ---- @@ -222,7 +222,7 @@ sub IOBASE () -> (X, Y) = $FFF3 ; read base address of I/O devices ~ c64util { -sub init_system () -> (A?, X?, Y?) { +sub init_system () -> (?) { ; ---- initializes the machine to a sane starting state ; This means that the BASIC, KERNAL and CHARGEN ROMs are banked in, ; the VIC, SID and CIA chips are reset, screen is cleared, and the default IRQ is set. @@ -253,7 +253,7 @@ sub init_system () -> (A?, X?, Y?) { } -sub FREADS32 () -> (A?, X?, Y?) { +sub FREADS32 () -> (?) { ; ---- fac1 = signed int32 from $62-$65 big endian (MSB FIRST) asm { lda $62 @@ -265,7 +265,7 @@ sub FREADS32 () -> (A?, X?, Y?) { } } -sub FREADUS32 () -> (A?, X?, Y?) { +sub FREADUS32 () -> (?) { ; ---- fac1 = uint32 from $62-$65 big endian (MSB FIRST) asm { sec @@ -275,7 +275,7 @@ sub FREADUS32 () -> (A?, X?, Y?) { } } -sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (A?, X?, Y?) { +sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (?) { ; ---- fac1 = signed int24 (A/X/Y contain lo/mid/hi bytes) ; note: there is no FREADU24AXY (unsigned), use FREADUS32 instead. asm { @@ -292,7 +292,7 @@ sub FREADS24AXY (lo: A, mid: X, hi: Y) -> (A?, X?, Y?) { } } -sub GIVUAYF (uword: AY) -> (A?, X?, Y?) { +sub GIVUAYF (uword: AY) -> (?) { ; ---- unsigned 16 bit word in A/Y (lo/hi) to fac1 asm { sty $62 @@ -303,7 +303,7 @@ sub GIVUAYF (uword: AY) -> (A?, X?, Y?) { } } -sub GIVAYFAY (sword: AY) -> (A?, X?, Y?) { +sub GIVAYFAY (sword: AY) -> (?) { ; ---- signed 16 bit word in A/Y (lo/hi) to float in fac1 asm { sta c64.SCRATCH_ZP1 @@ -439,7 +439,7 @@ hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as ; var .array(4) word2hex_output_array @todo support to use array/matrix type by address var .text word2hex_output = "123" ; 0-terminated, 4 bytes total @todo remove once array works -sub word2hex (word: XY) -> (A?, X?, Y?) { +sub word2hex (word: XY) -> (?) { ; ---- convert 16 bit word in X/Y into hexadecimal string into memory 'word2hex_output' asm { stx c64.SCRATCH_ZP2 @@ -495,7 +495,7 @@ sub word2bcd (word: XY) -> (A?, X?) { var .array(5) word2decimal_output -sub word2decimal (word: XY) -> (A?, X?, Y?) { +sub word2decimal (word: XY) -> (?) { ; ---- convert 16 bit word in X/Y into decimal string into memory 'word2decimal_output' asm { jsr word2bcd @@ -526,7 +526,7 @@ sub word2decimal (word: XY) -> (A?, X?, Y?) { } } -sub print_byte_decimal0 (ubyte: A) -> (A?, X?, Y?) { +sub print_byte_decimal0 (ubyte: A) -> (?) { ; ---- print the byte in A in decimal form, with left padding 0s (3 positions total) asm { jsr byte2decimal @@ -540,7 +540,7 @@ sub print_byte_decimal0 (ubyte: A) -> (A?, X?, Y?) { } } -sub print_byte_decimal (ubyte: A) -> (A?, X?, Y?) { +sub print_byte_decimal (ubyte: A) -> (?) { ; ---- print the byte in A in decimal form, without left padding 0s asm { jsr byte2decimal @@ -560,7 +560,7 @@ _print_tens txa } } -sub print_byte_hex (prefix: SC, ubyte: A) -> (A?, X?, Y?) { +sub print_byte_hex (prefix: SC, ubyte: A) -> (?) { ; ---- print the byte in A in hex form (if Carry is set, a radix prefix '$' is printed as well) asm { bcc + @@ -576,7 +576,7 @@ sub print_byte_hex (prefix: SC, ubyte: A) -> (A?, X?, Y?) { } } -sub print_word_hex (prefix: SC, word: XY) -> (A?, X?, Y?) { +sub print_word_hex (prefix: SC, word: XY) -> (?) { ; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits) ; (if Carry is set, a radix prefix '$' is printed as well) asm { @@ -590,7 +590,7 @@ sub print_word_hex (prefix: SC, word: XY) -> (A?, X?, Y?) { } -sub print_word_decimal0 (word: XY) -> (A?, X?, Y?) { +sub print_word_decimal0 (word: XY) -> (?) { ; ---- print the (unsigned) word in X/Y in decimal form, with left padding 0s (5 positions total) asm { jsr word2decimal @@ -665,7 +665,7 @@ sub input_chars (buffer: AX) -> (A?, Y) { } } -;sub memcopy_basic () -> (A?, X?, Y?) { +;sub memcopy_basic () -> (?) { ; ; ---- copy a memory block by using a BASIC ROM routine @todo fix code ; ; it calls a function from the basic interpreter, so: ; ; - BASIC ROM must be banked in diff --git a/lib/mathlib.ill b/lib/mathlib.ill index 364e09f97..3b57cf23f 100644 --- a/lib/mathlib.ill +++ b/lib/mathlib.ill @@ -68,7 +68,7 @@ sub multiply_bytes_addA_16 (byte1: X, byte2: Y, add: A) -> (A?, XY) { } var .wordarray(2) multiply_words_product -sub multiply_words (number: XY) -> (A?, X?, Y?) { ; @todo '?' to mean all 3 registers +sub multiply_words (number: XY) -> (?) { ; ---- multiply two 16-bit words into a 32-bit result ; input: X/Y = first 16-bit number, SCRATCH_ZPWORD1 in ZP = second 16-bit number ; output: multiply_words_product 32-bits product, LSB order (low-to-high) diff --git a/reference.md b/reference.md index 5c8471aa0..ee6e90708 100644 --- a/reference.md +++ b/reference.md @@ -306,6 +306,8 @@ The syntax is: is clobbered in the process so the original value it had before calling the sub is no longer valid. This is not immediately useful for your own code, but the compiler needs this information to emit the correct assembly code to preserve the cpu registers if needed when the call is made. + For convenience: a single '?' als the result spec is shorthand for ``A?, X?, Y?`` ("I don't know + what the changed registers are, assume the worst") Subroutines that are pre-defined on a specific memory location (usually routines from ROM), diff --git a/testsource/conditionals.ill b/testsource/conditionals.ill index aa3b1e371..17568e7a4 100644 --- a/testsource/conditionals.ill +++ b/testsource/conditionals.ill @@ -65,12 +65,12 @@ label3 if_not [$c000] goto label4 if_zero [$c000] goto label4 if [$c000] goto label4 - if_true [XY] goto label4 ; @todo support indirect reg - if_true [AY] goto label4 ; @todo support indirect reg - if_true [AX] goto label4 ; @todo support indirect reg - if_true [X] goto label4 ; @todo support indirect reg - if_true [A] goto label4 ; @todo support indirect reg - if_true [Y] goto label4 ; @todo support indirect reg + if_true [XY] goto label4 + if_true [AY] goto label4 + if_true [AX] goto label4 + if_true [X] goto label4 + if_true [A] goto label4 + if_true [Y] goto label4 label4 return diff --git a/testsource/floats.ill b/testsource/floats.ill index 87c3b5e2a..1f16e0619 100644 --- a/testsource/floats.ill +++ b/testsource/floats.ill @@ -43,7 +43,7 @@ start var .word wordvar = $cdef -sub printflt (float: AY) -> (A?, X?, Y?) { +sub printflt (float: AY) -> (?) { c64.MOVFM!(AY) goto c64.FPRINTLN ; c64.FOUT!() diff --git a/testsource/numbergame.ill b/testsource/numbergame.ill index 5855912b5..fc758df3e 100644 --- a/testsource/numbergame.ill +++ b/testsource/numbergame.ill @@ -1,6 +1,7 @@ output prg,basic ;reg_preserve off ; @todo global option off/on default off? + import "c64lib" diff --git a/todo.ill b/todo.ill index 379ff6301..d13929d8c 100644 --- a/todo.ill +++ b/todo.ill @@ -1,27 +1,11 @@ output prg,basic - -import "c64lib" -import "mathlib" - +;reg_preserve off ; @todo global option off/on default off? ~ main { ; zpvar myvar @todo allow for zp vars like this - var bytevar - var bytevar2 - var .word wordvar - var .float fl1 - var .float fl2 - start - ; XY() ; @todo better syntax error, need [XY] - [AX]() - [AY]() - [XY]() - [AX]!() - [AY]!() - [XY]!() - return + }