added new c64utils.str2(u)word that doesn't use kernel float routines

fixed processing of register pair return value of asmsub
This commit is contained in:
Irmen de Jong 2019-03-16 17:50:59 +01:00
parent 223bab21aa
commit 191707cd37
5 changed files with 143 additions and 140 deletions

View File

@ -168,140 +168,117 @@ asmsub uword2decimal (uword value @ AY) -> clobbers(A,Y) -> () {
}
asmsub str2byte (str string @ AY) -> clobbers(Y) -> (byte @ A) {
%asm {{
; -- convert string (address in A/Y) to byte in A
; doesn't use any kernal routines
sta c64.SCRATCH_ZPWORD1
sty c64.SCRATCH_ZPWORD1+1
ldy #0
lda (c64.SCRATCH_ZPWORD1),y
cmp #'-'
beq +
jmp str2ubyte._enter
+ inc c64.SCRATCH_ZPWORD1
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) {
; -- 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 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
_result = c64.SCRATCH_ZPWORD2
sta _mod+1
sty _mod+2
ldy #0
- lda ($22),y
beq +
iny
bne -
+ rts
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 {{
;-- 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
_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 #'+'
bne +
iny
+ cmp #'-'
bne _parse
inc _negative
iny
_parse lda (c64.SCRATCH_ZPWORD1),y
sec
sbc #48
bpl _digit
_done ; return result
lda _negative
beq +
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

View File

@ -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)
}

View File

@ -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)

View File

@ -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)

View File

@ -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')
}
}