correct printing of numbers

This commit is contained in:
Irmen de Jong 2018-12-14 23:15:44 +01:00
parent 7cb42de60e
commit 8597ea2ec7
9 changed files with 370 additions and 232 deletions

View File

@ -6,60 +6,220 @@
sub start() {
ubyte ub1
ubyte ub2
byte b1
byte b2
uword uw1
uword uw2
word w1
word w2
float f1
float f2
float f3
f1=22.555
f2=15.123
f3 = f1+f2
c64flt.print_float(f3)
; byte and ubyte output via print are all OK!
c64scr.print_byte_decimal(0)
c64.CHROUT(' ')
c64scr.print_byte_decimal(123)
c64.CHROUT(' ')
c64scr.print_byte_decimal(b2ub(-99)) ; @todo allow signed values for register
c64.CHROUT('\n')
c64scr.print_ubyte_decimal(0)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal0(0)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal(55)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal0(55)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal(254)
c64.CHROUT(' ')
c64scr.print_ubyte_decimal0(254)
c64.CHROUT('\n')
c64scr.print_ubyte_hex(0, 0)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(1, 0)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(0, $99)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(1, $99)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(0, $ea)
c64.CHROUT(' ')
c64scr.print_ubyte_hex(1, $ea)
c64.CHROUT('\n')
f1=22.555
f2=15.123
f3 = f1-f2
c64flt.print_float(f3)
; print_uword_decimal are all OK!
c64scr.print_uword_decimal(0)
c64.CHROUT(' ')
c64scr.print_uword_decimal0(0)
c64.CHROUT(' ')
c64scr.print_uword_decimal(987)
c64.CHROUT(' ')
c64scr.print_uword_decimal0(987)
c64.CHROUT(' ')
c64scr.print_uword_decimal(55666)
c64.CHROUT(' ')
c64scr.print_uword_decimal0(55666)
c64.CHROUT('\n')
c64scr.print_uword_hex(0, 0)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, 0)
c64.CHROUT(' ')
c64scr.print_uword_hex(0, $99)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, $99)
c64.CHROUT(' ')
c64scr.print_uword_hex(0, $1200)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, $1200)
c64.CHROUT(' ')
c64scr.print_uword_hex(0, $fe98)
c64.CHROUT(' ')
c64scr.print_uword_hex(1, $fe98)
c64.CHROUT('\n')
f1=22.555
f2=15.123
f3 = f1*f2
c64flt.print_float(f3)
; print_word_decimal works OK!
c64scr.print_word_decimal(0)
c64.CHROUT(' ')
c64scr.print_word_decimal(12345)
c64.CHROUT(' ')
c64scr.print_word_decimal(32555)
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-1)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-9999)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-$5fff)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-$6000)) ; @todo allow signed values for registerpair
c64.CHROUT(' ')
c64scr.print_word_decimal(uwrd(-$6001)) ; @todo allow signed values for registerpair
c64.CHROUT('\n')
f1=22.555
f2=15.123
f3 = f1/f2
c64flt.print_float(f3)
b1 = -6
b2 = 30
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('+')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 += b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
f3 = -f1
c64flt.print_float(f3)
b1 = 60
b2 = -3
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('+')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 += b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
f3++
c64flt.print_float(f3)
ub1 = 90
ub2 = 50
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('+')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 += ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
f3++
c64flt.print_float(f3)
ub1 = 50
ub2 = 90
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('+')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 += ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
f3++
c64flt.print_float(f3)
b1 = -6
b2 = 30
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('-')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 -= b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
f3--
c64flt.print_float(f3)
b1 = 60
b2 = -3
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('-')
c64scr.print_byte_decimal(b2ub(b2))
c64.CHROUT('=')
b1 -= b2
c64scr.print_byte_decimal(b2ub(b1))
c64.CHROUT('\n')
f3--
c64flt.print_float(f3)
ub1 = 90
ub2 = 50
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('-')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 -= ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
f3--
c64flt.print_float(f3)
ub1 = 50
ub2 = 90
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('-')
c64scr.print_ubyte_decimal(ub2)
c64.CHROUT('=')
ub1 -= ub2
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
w1 = -600
w2 = 30000
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('+')
c64scr.print_uword_hex(1, uwrd(w2))
c64.CHROUT('=')
w1 += w2
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('\n')
w1 = 600
w2 = -30000
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('+')
c64scr.print_uword_hex(1, uwrd(w2))
c64.CHROUT('=')
w1 += w2
c64scr.print_uword_hex(1, uwrd(w1))
c64.CHROUT('\n')
uw1 = 600
uw2 = 40000
c64scr.print_uword_decimal(uw1)
c64.CHROUT('+')
c64scr.print_uword_decimal(uw2)
c64.CHROUT('=')
uw1 += uw2
c64scr.print_uword_decimal(uw1)
c64.CHROUT('\n')
uw1 = 40000
uw2 = 600
c64scr.print_uword_decimal(uw1)
c64.CHROUT('+')
c64scr.print_uword_decimal(uw2)
c64.CHROUT('=')
uw1 += uw2
c64scr.print_uword_decimal(uw1)
c64.CHROUT('\n')
}
}

View File

@ -775,6 +775,10 @@ class PrefixExpression(val operator: String, var expression: IExpression, overri
override fun referencesIdentifier(name: String) = expression.referencesIdentifier(name)
override fun resultingDatatype(namespace: INameScope, heap: HeapValues): DataType? = expression.resultingDatatype(namespace, heap)
override fun isIterable(namespace: INameScope, heap: HeapValues) = false
override fun toString(): String {
return "Prefix($operator $expression)"
}
}

View File

@ -434,7 +434,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
val call = Syscall.values().find { it.callNr==ins.arg.numericValue() }
" jsr prog8_lib.${call.toString().toLowerCase()}"
when(call) {
Syscall.FUNC_WRD, Syscall.FUNC_UWRD -> ""
else -> " jsr prog8_lib.${call.toString().toLowerCase()}"
}
}
Opcode.BREAKPOINT -> {
breakpointCounter++

View File

@ -255,7 +255,7 @@ private fun builtinWrd(args: List<IExpression>, position: Position, namespace:IN
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.UBYTE && constval.type!=DataType.BYTE && constval.type!=DataType.UWORD)
throw SyntaxError("wrd requires one argument of type ubyte, byte or uword", position)
return LiteralValue(DataType.WORD, wordvalue = constval.bytevalue!!.toInt(), position = position)
return LiteralValue(DataType.WORD, wordvalue = constval.asIntegerValue, position = position)
}
private fun builtinUwrd(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -266,7 +266,7 @@ private fun builtinUwrd(args: List<IExpression>, position: Position, namespace:I
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE && constval.type!=DataType.WORD && constval.type!=DataType.UWORD)
throw SyntaxError("uwrd requires one argument of type byte, word or uword", position)
return LiteralValue(DataType.UWORD, wordvalue = constval.bytevalue!!.toInt(), position = position)
return LiteralValue(DataType.UWORD, wordvalue = constval.asIntegerValue!! and 65535, position = position)
}
private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue {
@ -275,8 +275,8 @@ private fun builtinB2ub(args: List<IExpression>, position: Position, namespace:I
throw SyntaxError("b2ub requires one byte argument", position)
val constval = args[0].constValue(namespace, heap) ?: throw NotConstArgumentException()
if(constval.type!=DataType.BYTE)
throw SyntaxError("b2ub requires one argument of type byte", position)
if(constval.type!=DataType.BYTE && constval.type!=DataType.UBYTE)
throw SyntaxError("b2ub requires one argument of type byte or ubyte", position)
return LiteralValue(DataType.UBYTE, bytevalue=(constval.bytevalue!!.toInt() and 255).toShort(), position = position)
}

View File

@ -5,7 +5,6 @@ import prog8.compiler.CompilerException
import prog8.compiler.HeapValues
import prog8.compiler.target.c64.FLOAT_MAX_NEGATIVE
import prog8.compiler.target.c64.FLOAT_MAX_POSITIVE
import prog8.compiler.target.c64.Petscii
import kotlin.math.floor

View File

@ -9,6 +9,7 @@ import prog8.ast.*
import prog8.compiler.*
import prog8.compiler.intermediate.Value
import prog8.compiler.target.c64.*
import java.io.CharConversionException
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
@ -272,8 +273,8 @@ class TestPetscii {
listOf<Short>(72, 69, 76, 76, 79, 32, 0xd7, 0xcf, 0xd2, 0xcc, 0xc4, 32, 49, 50, 51, 32, 64, 33, 0x5c)))
assertThat(Petscii.encodePetscii("\uf11a", true), equalTo(listOf<Short>(0x12))) // reverse vid
assertThat(Petscii.encodePetscii("", true), equalTo(listOf<Short>(0xfa)))
assertFailsWith<CompilerException> { Petscii.encodePetscii("π", true) }
assertFailsWith<CompilerException> { Petscii.encodePetscii("", true) }
assertFailsWith<CharConversionException> { Petscii.encodePetscii("π", true) }
assertFailsWith<CharConversionException> { Petscii.encodePetscii("", true) }
assertThat(Petscii.decodePetscii(listOf(72, 0xd7, 0x5c, 0xfa, 0x12), true), equalTo("hW£✓\uF11A"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodePetscii(listOf(-1), true) }
@ -287,7 +288,7 @@ class TestPetscii {
assertThat(Petscii.encodePetscii("\uf11a"), equalTo(listOf<Short>(0x12))) // reverse vid
assertThat(Petscii.encodePetscii(""), equalTo(listOf<Short>(0xd3)))
assertThat(Petscii.encodePetscii("π"), equalTo(listOf<Short>(0xff)))
assertFailsWith<CompilerException> { Petscii.encodePetscii("") }
assertFailsWith<CharConversionException> { Petscii.encodePetscii("") }
assertThat(Petscii.decodePetscii(listOf(72, 0x5c, 0xd3, 0xff)), equalTo("H£♥π"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodePetscii(listOf(-1)) }
@ -300,8 +301,8 @@ class TestPetscii {
listOf<Short>(0x08, 0x05, 0x0c, 0x0c, 0x0f, 0x20, 0x57, 0x4f, 0x52, 0x4c, 0x44, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c)
))
assertThat(Petscii.encodeScreencode("", true), equalTo(listOf<Short>(0x7a)))
assertFailsWith<CompilerException> { Petscii.encodeScreencode("", true) }
assertFailsWith<CompilerException> { Petscii.encodeScreencode("π", true) }
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("", true) }
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("π", true) }
assertThat(Petscii.decodeScreencode(listOf(0x08, 0x57, 0x1c, 0x7a), true), equalTo("hW£✓"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodeScreencode(listOf(-1), true) }
@ -314,8 +315,8 @@ class TestPetscii {
listOf<Short>(0x17, 0x0f, 0x12, 0x0c, 0x04, 0x20, 0x31, 0x32, 0x33, 0x20, 0x00, 0x21, 0x1c)))
assertThat(Petscii.encodeScreencode(""), equalTo(listOf<Short>(0x53)))
assertThat(Petscii.encodeScreencode("π"), equalTo(listOf<Short>(0x5e)))
assertFailsWith<CompilerException> { Petscii.encodeScreencode("") }
assertFailsWith<CompilerException> { Petscii.encodeScreencode("hello") }
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("") }
assertFailsWith<CharConversionException> { Petscii.encodeScreencode("hello") }
assertThat(Petscii.decodeScreencode(listOf(0x17, 0x1c, 0x53, 0x5e)), equalTo("W£♥π"))
assertFailsWith<ArrayIndexOutOfBoundsException> { Petscii.decodeScreencode(listOf(-1)) }

View File

@ -44,7 +44,7 @@ asmsub init_system () -> clobbers(A,X,Y) -> () {
}}
}
asmsub byte2decimal (value: ubyte @ A) -> clobbers() -> (ubyte @ Y, ubyte @ X, ubyte @ A) {
asmsub ubyte2decimal (value: ubyte @ A) -> clobbers() -> (ubyte @ Y, ubyte @ X, ubyte @ A) {
; ---- A to decimal string in Y/X/A (100s in Y, 10s in X, 1s in A)
%asm {{
ldy #$2f
@ -61,8 +61,21 @@ asmsub byte2decimal (value: ubyte @ A) -> clobbers() -> (ubyte @ Y, ubyte @ X,
}}
}
asmsub byte2hex (value: ubyte @ A) -> clobbers(A) -> (ubyte @ X, ubyte @ Y) {
; ---- A to hex string in XY (first hex char in X, second hex char in Y)
asmsub byte2decimal (value: ubyte @ A) -> clobbers() -> (ubyte @ Y, ubyte @ X, ubyte @ A) {
; ---- A (signed byte) to decimal string in Y/X/A (100s in Y, 10s in X, 1s in A)
; note: the '-' is not part of the conversion here if it's a negative number
%asm {{
cmp #0
bpl +
eor #255
clc
adc #1
+ jmp ubyte2decimal
}}
}
asmsub ubyte2hex (value: ubyte @ A) -> clobbers(X) -> (ubyte @ A, ubyte @ Y) {
; ---- A to hex string in AY (first hex char in A, second hex char in Y)
%asm {{
pha
and #$0f
@ -75,7 +88,6 @@ asmsub byte2hex (value: ubyte @ A) -> clobbers(A) -> (ubyte @ X, ubyte @ Y) {
lsr a
tax
lda hex_digits,x
tax
rts
hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as well
@ -84,33 +96,33 @@ hex_digits .text "0123456789abcdef" ; can probably be reused for other stuff as
str word2hex_output = "1234" ; 0-terminated, to make printing easier
asmsub word2hex (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- convert 16 bit word in X/Y into 4-character hexadecimal string into memory 'word2hex_output'
asmsub uword2hex (value: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- convert 16 bit uword in A/Y into 4-character hexadecimal string into memory 'word2hex_output'
%asm {{
stx c64.SCRATCH_ZPREG
sta c64.SCRATCH_ZPREG
tya
jsr byte2hex
jsr ubyte2hex
stx word2hex_output
sty word2hex_output+1
lda c64.SCRATCH_ZPREG
jsr byte2hex
stx word2hex_output+2
jsr ubyte2hex
sta word2hex_output+2
sty word2hex_output+3
rts
}}
}
ubyte[3] word2bcd_bcdbuff = [0, 0, 0]
asmsub word2bcd (dataword: uword @ XY) -> clobbers(A,X) -> () {
asmsub uword2bcd (dataword: uword @ AY) -> clobbers(A,X) -> () {
; Convert an 16 bit binary value to BCD
;
; This function converts a 16 bit binary value in X/Y into a 24 bit BCD. It
; This function converts a 16 bit binary value in A/Y into a 24 bit BCD. It
; works by transferring one bit a time from the source and adding it
; into a BCD value that is being doubled on each iteration. As all the
; arithmetic is being done in BCD the result is a binary to decimal
; conversion.
%asm {{
stx c64.SCRATCH_ZPB1
sta c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
sed ; switch to decimal mode
lda #0 ; ensure the result is clear
@ -139,10 +151,10 @@ asmsub word2bcd (dataword: uword @ XY) -> clobbers(A,X) -> () {
ubyte[5] word2decimal_output = 0
asmsub word2decimal (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- convert 16 bit word in X/Y into decimal string into memory 'word2decimal_output'
asmsub uword2decimal (dataword: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- convert 16 bit uword in A/Y into decimal string into memory 'word2decimal_output'
%asm {{
jsr word2bcd
jsr uword2bcd
lda word2bcd_bcdbuff+2
clc
adc #'0'
@ -264,102 +276,10 @@ asmsub GETADRAY () -> clobbers(X) -> (uword @ AY) {
}}
}
asmsub copy_mflt (source: uword @ XY) -> clobbers(A) -> () {
; ---- copy a 5 byte MFLT floating point variable to another place
; input: X/Y = source address, c64.SCRATCH_ZPWORD1 = destination address
%asm {{
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPWORD1+1
ldy #0
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
iny
lda (c64.SCRATCH_ZPB1),y
sta (c64.SCRATCH_ZPWORD1),y
ldy c64.SCRATCH_ZPWORD1+1
rts
}}
}
asmsub float_add_one (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- add 1 to the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
txa
jsr c64.MOVFM ; fac1 = float XY
lda #<c64.FL_FONE
ldy #>c64.FL_FONE
jsr c64.FADD ; fac1 += 1
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.MOVMF ; float XY = fac1
}}
}
asmsub float_sub_one (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- subtract 1 from the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
lda #<c64.FL_FONE
ldy #>c64.FL_FONE
jsr c64.MOVFM ; fac1 = 1
txa
ldy c64.SCRATCH_ZPREG
jsr c64.FSUB ; fac1 = float XY - 1
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.MOVMF ; float XY = fac1
}}
}
asmsub float_add_SW1_to_XY (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- add MFLT pointed to by SCRATCH_ZPWORD1 to the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
txa
jsr c64.MOVFM ; fac1 = float XY
lda c64.SCRATCH_ZPWORD1
ldy c64.SCRATCH_ZPWORD1+1
jsr c64.FADD ; fac1 += SCRATCH_ZPWORD1
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.MOVMF ; float XY = fac1
}}
}
asmsub float_sub_SW1_from_XY (mflt: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- subtract MFLT pointed to by SCRATCH_ZPWORD1 from the MFLT pointed to by X/Y. Clobbers A, X, Y
%asm {{
stx c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
lda c64.SCRATCH_ZPWORD1
ldy c64.SCRATCH_ZPWORD1+1
jsr c64.MOVFM ; fac1 = SCRATCH_ZPWORD1
txa
ldy c64.SCRATCH_ZPREG
jsr c64.FSUB ; fac1 = float XY - SCRATCH_ZPWORD1
ldx c64.SCRATCH_ZPB1
ldy c64.SCRATCH_ZPREG
jmp c64.MOVMF ; float XY = fac1
}}
}
sub print_float (value: float) {
; ---- prints the floating point value (without a newline) using basic rom routines.
; clobbers no registers.
; @todo version that takes A/Y pointer to float instead
%asm {{
pha
tya
@ -383,6 +303,7 @@ sub print_float (value: float) {
sub print_float_ln (value: float) {
; ---- prints the floating point value (with a newline at the end) using basic rom routines
; clobbers no registers.
; @todo version that takes A/Y pointer to float instead
%asm {{
pha
tya
@ -654,13 +575,13 @@ _scroll_screen ; scroll the screen memory
asmsub print_string (text: str @ XY) -> clobbers(A,Y) -> () {
; ---- print null terminated string from X/Y
asmsub print_string (text: str @ AY) -> clobbers(A,Y) -> () {
; ---- print null terminated string from A/Y
; note: the compiler contains an optimization that will replace
; a call to this subroutine with a string argument of just one char,
; by just one call to c64.CHROUT of that single char. @todo do this
%asm {{
stx c64.SCRATCH_ZPB1
sta c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
ldy #0
- lda (c64.SCRATCH_ZPB1),y
@ -673,10 +594,10 @@ asmsub print_string (text: str @ XY) -> clobbers(A,Y) -> () {
}
asmsub print_pstring (text: str_p @ XY) -> clobbers(A,X) -> (ubyte @ Y) {
; ---- print pstring (length as first byte) from X/Y, returns str len in Y
asmsub print_pstring (text: str_p @ AY) -> clobbers(A,X) -> (ubyte @ Y) {
; ---- print pstring (length as first byte) from A/Y, returns str len in Y
%asm {{
stx c64.SCRATCH_ZPB1
sta c64.SCRATCH_ZPB1
sty c64.SCRATCH_ZPREG
ldy #0
lda (c64.SCRATCH_ZPB1),y
@ -692,10 +613,10 @@ asmsub print_pstring (text: str_p @ XY) -> clobbers(A,X) -> (ubyte @ Y) {
}
asmsub print_byte_decimal0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the byte in A in decimal form, with left padding 0s (3 positions total)
asmsub print_ubyte_decimal0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
%asm {{
jsr c64utils.byte2decimal
jsr c64utils.ubyte2decimal
pha
tya
jsr c64.CHROUT
@ -707,10 +628,11 @@ asmsub print_byte_decimal0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
}
asmsub print_byte_decimal (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the byte in A in decimal form, without left padding 0s
asmsub print_ubyte_decimal (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the ubyte in A in decimal form, without left padding 0s
%asm {{
jsr c64utils.byte2decimal
jsr c64utils.ubyte2decimal
_print_byte_digits
pha
cpy #'0'
bne _print_hundreds
@ -726,18 +648,31 @@ _print_tens txa
jmp c64.CHROUT
}}
}
asmsub print_byte_decimal (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the byte in A in decimal form, without left padding 0s
%asm {{
pha
cmp #0
bpl +
lda #'-'
jsr c64.CHROUT
+ pla
jsr c64utils.byte2decimal
jmp print_ubyte_decimal._print_byte_digits
}}
}
asmsub print_byte_hex (prefix: ubyte @ Pc, value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the byte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
asmsub print_ubyte_hex (prefix: ubyte @ Pc, value: ubyte @ A) -> clobbers(A,X,Y) -> () {
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
%asm {{
bcc +
pha
lda #'$'
jsr c64.CHROUT
pla
+ jsr c64utils.byte2hex
txa
+ jsr c64utils.ubyte2hex
jsr c64.CHROUT
tya
jmp c64.CHROUT
@ -745,25 +680,25 @@ asmsub print_byte_hex (prefix: ubyte @ Pc, value: ubyte @ A) -> clobbers(A,X,Y
}
asmsub print_word_hex (prefix: ubyte @ Pc, dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- print the (unsigned) word in X/Y in hexadecimal form (4 digits)
asmsub print_uword_hex (prefix: ubyte @ Pc, value: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- print the uword in A/Y in hexadecimal form (4 digits)
; (if Carry is set, a radix prefix '$' is printed as well)
%asm {{
stx c64.SCRATCH_ZPB1
pha
tya
jsr print_byte_hex
lda c64.SCRATCH_ZPB1
jsr print_ubyte_hex
pla
clc
jmp print_byte_hex
jmp print_ubyte_hex
}}
}
asmsub print_word_decimal0 (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- print the (unsigned) word in X/Y in decimal form, with left padding 0s (5 positions total)
asmsub print_uword_decimal0 (value: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
; @todo shorter in loop form?
%asm {{
jsr c64utils.word2decimal
jsr c64utils.uword2decimal
lda c64utils.word2decimal_output
jsr c64.CHROUT
lda c64utils.word2decimal_output+1
@ -778,10 +713,10 @@ asmsub print_word_decimal0 (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
}
asmsub print_word_decimal (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
; ---- print the word in X/Y in decimal form, without left padding 0s
asmsub print_uword_decimal (value: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- print the uword in A/Y in decimal form, without left padding 0s
%asm {{
jsr c64utils.word2decimal
jsr c64utils.uword2decimal
ldy #0
lda c64utils.word2decimal_output
cmp #'0'
@ -810,6 +745,26 @@ _pr_decimal
}}
}
asmsub print_word_decimal (value: uword @ AY) -> clobbers(A,X,Y) -> () {
; ---- print the (signed) word in A/Y in decimal form, without left padding 0s
%asm {{
cpy #0
bpl +
pha
lda #'-'
jsr c64.CHROUT
tya
eor #255
tay
pla
eor #255
clc
adc #1
bcc +
iny
+ jmp print_uword_decimal
}}
}
asmsub input_chars (buffer: uword @ AY) -> clobbers(A, X) -> (ubyte @ Y) {
; ---- Input a string (max. 80 chars) from the keyboard. Returns length in Y.

View File

@ -19,10 +19,10 @@
asmsub multiply_bytes (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(X) -> (ubyte @ A) {
asmsub multiply_bytes (byte1: ubyte @ A, byte2: ubyte @ Y) -> clobbers(X) -> (ubyte @ A) {
; ---- multiply 2 bytes, result as byte in A (signed or unsigned)
%asm {{
stx SCRATCH_ZPB1
sta SCRATCH_ZPB1
sty SCRATCH_ZPREG
ldx #8
- asl a
@ -37,12 +37,12 @@ asmsub multiply_bytes (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(X) -> (
}
asmsub multiply_bytes_16 (byte1: ubyte @ X, byte2: ubyte @ Y) -> clobbers(A) -> (uword @ XY) {
; ---- multiply 2 bytes, result as word in X/Y (unsigned)
asmsub multiply_bytes_16 (byte1: ubyte @ A, byte2: ubyte @ Y) -> clobbers(X) -> (uword @ AY) {
; ---- multiply 2 bytes, result as word in A/Y (unsigned)
%asm {{
lda #0
_m_with_add stx SCRATCH_ZPB1
sta SCRATCH_ZPB1
sty SCRATCH_ZPREG
lda #0
ldx #8
lsr SCRATCH_ZPB1
- bcc +
@ -53,26 +53,19 @@ _m_with_add stx SCRATCH_ZPB1
dex
bne -
tay
ldx SCRATCH_ZPB1
lda SCRATCH_ZPB1
rts
}}
}
asmsub multiply_bytes_addA_16 (byte1: ubyte @ X, byte2: ubyte @ Y, add: ubyte @ A) -> clobbers(A) -> (uword @ XY) {
; ---- multiply 2 bytes and add A, result as word in X/Y (unsigned)
%asm {{
jmp multiply_bytes_16._m_with_add
}}
}
word[2] multiply_words_product = 0
asmsub multiply_words (number: uword @ XY) -> clobbers(A,X) -> () {
asmsub multiply_words (number: uword @ AY) -> clobbers(A,X) -> () {
; ---- 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
; input: A/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)
%asm {{
stx SCRATCH_ZPWORD2
sta SCRATCH_ZPWORD2
sty SCRATCH_ZPWORD2+1
mult16 lda #$00
@ -123,16 +116,16 @@ asmsub divmod_bytes (number: ubyte @ X, divisor: ubyte @ Y) -> clobbers() -> (
}}
}
asmsub divmod_words (divisor: uword @ XY) -> clobbers(A) -> (uword @ XY) {
asmsub divmod_words (divisor: uword @ AY) -> clobbers(X) -> (uword @ AY) {
; ---- divide two words (16 bit each) into 16 bit results
; input: SCRATCH_ZPWORD1 in ZP: 16 bit number, X/Y: 16 bit divisor
; output: SCRATCH_ZPWORD1 in ZP: 16 bit result, X/Y: 16 bit remainder
; input: SCRATCH_ZPWORD1 in ZP: 16 bit number, A/Y: 16 bit divisor
; output: SCRATCH_ZPWORD1 in ZP: 16 bit result, A/Y: 16 bit remainder
; division by zero will result in quotient = 65535 and remainder = divident
%asm {{
remainder = SCRATCH_ZPB1
stx SCRATCH_ZPWORD2
sta SCRATCH_ZPWORD2
sty SCRATCH_ZPWORD2+1
lda #0 ;preset remainder to 0
sta remainder
@ -163,7 +156,7 @@ remainder = SCRATCH_ZPB1
lda remainder+1
sta SCRATCH_ZPWORD2+1
ldx SCRATCH_ZPWORD1 ; load division result in X/Y
lda SCRATCH_ZPWORD1 ; load division result in A/Y
ldy SCRATCH_ZPWORD1+1
rts
@ -211,8 +204,8 @@ _magiceors .byte $1d, $2b, $2d, $4d, $5f, $63, $65, $69
}}
}
asmsub randword () -> clobbers() -> (uword @ XY) {
; ---- 16 bit pseudo random number generator into XY
asmsub randword () -> clobbers() -> (uword @ AY) {
; ---- 16 bit pseudo random number generator into AY
%asm {{
lda _seed
@ -230,7 +223,6 @@ _doEor ; high byte is in A
lda _seed
eor _magic ; #<magic ; could be self-modifying code to set new magic
sta _seed
tax
ldy _seed+1
rts
@ -246,7 +238,7 @@ _lowZero lda _seed+1
_noEor sta _seed+1
tay
ldx _seed
lda _seed
rts

View File

@ -7,7 +7,7 @@
~ prog8_lib {
; @TODO move all this assembly to a real .asm file instead and include that...
; note: the following ZP scratch registers must be the same as in c64lib
memory ubyte SCRATCH_ZPB1 = $02 ; scratch byte 1 in ZP
@ -116,22 +116,33 @@ push_float .proc
add_a_to_zpword .proc
; -- add ubyte in A to the uword in SCRATCH_ZPWORD1
rts
.warn "not implemented"
.pend
push_float_from_indexed_var .proc
; -- push the float from the array at A/Y with index on stack, back on the stack.
clc
adc SCRATCH_ZPWORD1
sta SCRATCH_ZPWORD1
sty SCRATCH_ZPWORD1+1
bvc +
inc SCRATCH_ZPWORD1+1
+ rts
.pend
pop_index_times_5 .proc
inx
lda ESTACK_LO,x
sta SCRATCH_ZPB1
asl a
asl a
clc
adc SCRATCH_ZPB1
adc SCRATCH_ZPB1 ; A*=5
rts
.pend
push_float_from_indexed_var .proc
; -- push the float from the array at A/Y with index on stack, onto the stack.
sta SCRATCH_ZPWORD1
sty SCRATCH_ZPWORD1+1
jsr pop_index_times_5
jsr add_a_to_zpword
lda SCRATCH_ZPWORD1
ldy SCRATCH_ZPWORD1+1
jmp push_float
.pend
@ -162,8 +173,14 @@ pop_float .proc
.pend
pop_float_to_indexed_var .proc
rts
.warn "not implemented"
; -- pop the float on the stack, to the memory in the array at A/Y indexed by the byte on stack
sta SCRATCH_ZPWORD1
sty SCRATCH_ZPWORD1+1
jsr pop_index_times_5
jsr add_a_to_zpword
lda SCRATCH_ZPWORD1
ldy SCRATCH_ZPWORD1+1
jmp pop_float
.pend
copy_float .proc
@ -306,13 +323,30 @@ neg_f .proc
add_w .proc
rts ; @todo inline?
.warn "not implemented"
; -- push word+word
.warn "addw"
inx
clc
lda ESTACK_LO,x
adc ESTACK_LO+1,x
sta ESTACK_LO+1,x
lda ESTACK_HI,x
adc ESTACK_HI+1,x
sta ESTACK_HI+1,x
rts
.pend
add_uw .proc
rts ; @todo inline?
.warn "not implemented"
.warn "add_uw"
inx
clc
lda ESTACK_LO,x
adc ESTACK_LO+1,x
sta ESTACK_LO+1,x
lda ESTACK_HI,x
adc ESTACK_HI+1,x
sta ESTACK_HI+1,x
rts
.pend
sub_w .proc
@ -850,16 +884,6 @@ _rndf_rnum5 .fill 5
.pend
func_wrd .proc
rts
.warn "not implemented"
.pend
func_uwrd .proc
rts
.warn "not implemented"
.pend
func_str2byte .proc
rts
.warn "not implemented"