From 191707cd3775b20a5600ed6ac283eb0f3bdc5f19 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 16 Mar 2019 17:50:59 +0100 Subject: [PATCH] added new c64utils.str2(u)word that doesn't use kernel float routines fixed processing of register pair return value of asmsub --- compiler/res/prog8lib/c64utils.p8 | 219 +++++++++++------------- compiler/src/prog8/ast/AstChecker.kt | 6 - compiler/src/prog8/compiler/Compiler.kt | 11 +- examples/numbergame.p8 | 2 +- examples/test.p8 | 45 ++++- 5 files changed, 143 insertions(+), 140 deletions(-) diff --git a/compiler/res/prog8lib/c64utils.p8 b/compiler/res/prog8lib/c64utils.p8 index 84e56ec80..e86f77569 100644 --- a/compiler/res/prog8lib/c64utils.p8 +++ b/compiler/res/prog8lib/c64utils.p8 @@ -168,140 +168,117 @@ asmsub uword2decimal (uword value @ AY) -> clobbers(A,Y) -> () { } -asmsub str2byte (str string @ AY) -> clobbers(Y) -> (byte @ A) { +asmsub str2uword(str string @ AY) -> clobbers() -> (uword @ AY) { + ; -- returns the unsigned word value of the string number argument in AY + ; the number may NOT be preceded by a + sign and may NOT contain spaces + ; (any non-digit character will terminate the number string that is parsed) %asm {{ - ; -- convert string (address in A/Y) to byte in A - ; doesn't use any kernal routines +_result = c64.SCRATCH_ZPWORD2 + sta _mod+1 + sty _mod+2 + ldy #0 + sty _result + sty _result+1 +_mod lda $ffff,y ; modified + sec + sbc #48 + bpl + +_done ; return result + lda _result + ldy _result+1 + rts ++ cmp #10 + bcs _done + ; add digit to result + pha + jsr _result_times_10 + pla + clc + adc _result + sta _result + bcc + + inc _result+1 ++ iny + bne _mod + ; never reached + +_result_times_10 ; (W*4 + W)*2 + lda _result+1 + sta c64.SCRATCH_ZPREG + lda _result + asl a + rol c64.SCRATCH_ZPREG + asl a + rol c64.SCRATCH_ZPREG + clc + adc _result + sta _result + lda c64.SCRATCH_ZPREG + adc _result+1 + asl _result + rol a + sta _result+1 + rts + }} +} + + +asmsub str2word(str string @ AY) -> clobbers() -> (word @ AY) { + ; -- returns the signed word value of the string number argument in AY + ; the number may be preceded by a + or - sign but may NOT contain spaces + ; (any non-digit character will terminate the number string that is parsed) + %asm {{ +_result = c64.SCRATCH_ZPWORD2 sta c64.SCRATCH_ZPWORD1 sty c64.SCRATCH_ZPWORD1+1 ldy #0 + sty _result + sty _result+1 + sty _negative lda (c64.SCRATCH_ZPWORD1),y - cmp #'-' - beq + - jmp str2ubyte._enter -+ inc c64.SCRATCH_ZPWORD1 + cmp #'+' bne + - inc c64.SCRATCH_ZPWORD1+1 -+ jsr str2ubyte._enter - eor #$ff - sec - adc #0 - rts - }} -} - -asmsub str2ubyte (str string @ AY) -> clobbers(Y) -> (ubyte @ A) { - %asm {{ - ; -- convert string (address in A/Y) to ubyte in A - ; doesn't use any kernal routines - sta c64.SCRATCH_ZPWORD1 - sty c64.SCRATCH_ZPWORD1+1 -_enter jsr _numlen ; Y= slen - lda #0 - dey - bpl + - rts -+ lda (c64.SCRATCH_ZPWORD1),y - sec - sbc #'0' - dey - bpl + - rts -+ sta c64.SCRATCH_ZPREG ;result - lda (c64.SCRATCH_ZPWORD1),y - sec - sbc #'0' - asl a - sta c64.SCRATCH_ZPB1 - asl a - asl a - clc - adc c64.SCRATCH_ZPB1 - clc - adc c64.SCRATCH_ZPREG - dey - bpl + - rts -+ sta c64.SCRATCH_ZPREG - lda (c64.SCRATCH_ZPWORD1),y - tay - lda _hundreds-'0',y - clc - adc c64.SCRATCH_ZPREG - rts -_hundreds .byte 0, 100, 200 - -_numlen - ;-- return the length of the numeric string at ZPWORD1, in Y - ldy #0 -- lda (c64.SCRATCH_ZPWORD1),y - cmp #'0' - bmi + - cmp #':' ; one after '9' - bpl + iny - bne - -+ rts - - }} -} - - -asmsub c64flt_FREADSTR (ubyte length @ A) -> clobbers(A,X,Y) -> () = $b7b5 ; @todo needed for (slow) str conversion below -asmsub c64flt_GETADR () -> clobbers(X) -> (ubyte @ Y, ubyte @ A) = $b7f7 ; @todo needed for (slow) str conversion below -asmsub c64flt_FTOSWORDYA () -> clobbers(X) -> (ubyte @ Y, ubyte @ A) = $b1aa ; @todo needed for (slow) str conversion below - -asmsub str2uword(str string @ AY) -> clobbers() -> (uword @ AY) { - %asm {{ - ;-- convert string (address in A/Y) to uword number in A/Y - ; @todo don't use the (slow) kernel floating point conversion - sta $22 - sty $23 - jsr _strlen2233 - tya - stx c64.SCRATCH_ZPREGX - jsr c64flt_FREADSTR ; string to fac1 - jsr c64flt_GETADR ; fac1 to unsigned word in Y/A - ldx c64.SCRATCH_ZPREGX - sta c64.SCRATCH_ZPREG - tya - ldy c64.SCRATCH_ZPREG - rts - -_strlen2233 - ;-- return the length of the (zero-terminated) string at $22/$23, in Y - ldy #0 -- lda ($22),y ++ cmp #'-' + bne _parse + inc _negative + iny +_parse lda (c64.SCRATCH_ZPWORD1),y + sec + sbc #48 + bpl _digit +_done ; return result + lda _negative beq + - iny - bne - -+ rts - }} -} - -asmsub str2word(str string @ AY) -> clobbers() -> (word @ AY) { - %asm {{ - ;-- convert string (address in A/Y) to signed word number in A/Y - ; @todo don't use the (slow) kernel floating point conversion - sta $22 - sty $23 - jsr str2uword._strlen2233 - tya - stx c64.SCRATCH_ZPREGX - jsr c64flt_FREADSTR ; string to fac1 - jsr c64flt_FTOSWORDYA ; fac1 to unsigned word in Y/A - ldx c64.SCRATCH_ZPREGX - sta c64.SCRATCH_ZPREG - tya - ldy c64.SCRATCH_ZPREG + sec + lda #0 + sbc _result + sta _result + lda #0 + sbc _result+1 + sta _result+1 ++ lda _result + ldy _result+1 rts +_digit cmp #10 + bcs _done + ; add digit to result + pha + jsr str2uword._result_times_10 + pla + clc + adc _result + sta _result + bcc + + inc _result+1 ++ iny + bne _parse + ; never reached +_negative .byte 0 }} } -; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html - - asmsub set_irqvec_excl() -> clobbers(A) -> () { %asm {{ sei diff --git a/compiler/src/prog8/ast/AstChecker.kt b/compiler/src/prog8/ast/AstChecker.kt index f86f14b8c..f55225435 100644 --- a/compiler/src/prog8/ast/AstChecker.kt +++ b/compiler/src/prog8/ast/AstChecker.kt @@ -727,12 +727,6 @@ private class AstChecker(private val namespace: INameScope, override fun process(typecast: TypecastExpression): IExpression { if(typecast.type in IterableDatatypes) checkResult.add(ExpressionError("cannot type cast to string or array type", typecast.position)) - val funcTarget = (typecast.expression as? IFunctionCall)?.target?.targetStatement(namespace) - if(funcTarget is Subroutine && - funcTarget.asmReturnvaluesRegisters.isNotEmpty() && - funcTarget.asmReturnvaluesRegisters.all { it.stack!=true }) { - checkResult.add(ExpressionError("cannot type cast a call to an asmsub that returns value in register - use a variable to store it first", typecast.position)) - } return super.process(typecast) } diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index 08abce6e0..ee2ccb660 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -1016,7 +1016,9 @@ internal class Compiler(private val rootModule: Module, TODO("not yet supported: return values in cpu status flag $rv $subroutine") when(rv.registerOrPair) { A,X,Y -> prog.instr(Opcode.PUSH_VAR_BYTE, callLabel = rv.registerOrPair.name) - AX, AY, XY -> prog.instr(Opcode.PUSH_VAR_WORD, callLabel = rv.registerOrPair.name) + AX -> prog.instr(Opcode.PUSH_REGAX_WORD) + AY -> prog.instr(Opcode.PUSH_REGAY_WORD) + XY -> prog.instr(Opcode.PUSH_REGXY_WORD) null -> {} } } @@ -2146,13 +2148,6 @@ internal class Compiler(private val rootModule: Module, } private fun translate(expr: TypecastExpression) { - val funcTarget = (expr.expression as? IFunctionCall)?.target?.targetStatement(namespace) - if(funcTarget is Subroutine && - funcTarget.asmReturnvaluesRegisters.isNotEmpty() && - funcTarget.asmReturnvaluesRegisters.all { it.stack!=true }) { - throw CompilerException("cannot type cast a call to an asmsub that returns value in register - use a variable to store it first") - } - translate(expr.expression) val sourceDt = expr.expression.resultingDatatype(namespace, heap) ?: throw CompilerException("don't know what type to cast") if(sourceDt==expr.type) diff --git a/examples/numbergame.p8 b/examples/numbergame.p8 index 74637f9fc..f980cc05d 100644 --- a/examples/numbergame.p8 +++ b/examples/numbergame.p8 @@ -29,7 +29,7 @@ c64scr.print("es") c64scr.print(" left.\nWhat is your next guess? ") c64scr.input_chars(input) - ubyte guess = c64utils.str2ubyte(input) + ubyte guess = lsb(c64utils.str2uword(input)) if guess==secretnumber { return ending(true) diff --git a/examples/test.p8 b/examples/test.p8 index 1054ac3ad..88769a1cb 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,9 +7,46 @@ sub start() { - ubyte ub - A = 123 or 44 - Y = A or 1 - ub = ub or 1 + uword z = c64utils.str2uword(" 1 2 3 4 5 ") + c64scr.print_uw(c64utils.str2uword(" ")) + c64.CHROUT('\n') + c64scr.print_uw(c64utils.str2uword(" 222 ")) + c64.CHROUT('\n') + c64scr.print_uw(c64utils.str2uword("1234 567")) + c64.CHROUT('\n') + c64scr.print_uw(c64utils.str2uword("1234x567")) + c64.CHROUT('\n') + c64scr.print_uw(c64utils.str2uword("+1234x567")) + c64.CHROUT('\n') + c64scr.print_uw(c64utils.str2uword("00065534")) + c64.CHROUT('\n') + c64scr.print_uw(c64utils.str2uword("0006553x4")) + c64.CHROUT('\n') + c64.CHROUT('\n') + + word z2 = c64utils.str2word(" 1 2 3 4 5 ") + c64scr.print_w(c64utils.str2word(" ")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("0000000")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("12345")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("64444")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word(" 12345")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("-12345")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word(" - 123 45")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("+1234 567 ")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("-1234 567 ")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("-31999")) + c64.CHROUT('\n') + c64scr.print_w(c64utils.str2word("31999")) + c64.CHROUT('\n') } + }