more asm, constants now also outputted in asm source

This commit is contained in:
Irmen de Jong 2018-12-04 22:30:35 +01:00
parent 08224d5367
commit 0c64d7ffe5
9 changed files with 200 additions and 121 deletions

View File

@ -1,7 +1,6 @@
%output prg %output prg
%import c64lib %import c64lib
%import c64utils %import c64utils
%import mathlib
~ main { ~ main {
sub start() { sub start() {
@ -28,7 +27,7 @@
c64.MUL10() ; .. and now *100 c64.MUL10() ; .. and now *100
c64.FADDH() ; add 0.5.. c64.FADDH() ; add 0.5..
c64.FADDH() ; and again, so +1 total c64.FADDH() ; and again, so +1 total
A, Y = c64flt.GETADRAY() ; @todo fix return value type check "cannot assign word to byte, use msb() or lsb()" A, Y = c64flt.GETADRAY()
secretnumber = A secretnumber = A
c64scr.print_string("I am thinking of a number from 1 to 100!You'll have to guess it!\n") c64scr.print_string("I am thinking of a number from 1 to 100!You'll have to guess it!\n")
@ -44,7 +43,7 @@ ask_guess:
c64.CHROUT('\n') c64.CHROUT('\n')
freadstr_arg = guess freadstr_arg = guess
c64.FREADSTR(A) c64.FREADSTR(A)
A, Y = c64flt.GETADRAY() ; @todo fix return value type check "cannot assign word to byte, use msb() or lsb()" A, Y = c64flt.GETADRAY()
if(A==secretnumber) { if(A==secretnumber) {
c64scr.print_string("\nThat's my number, impressive!\n") c64scr.print_string("\nThat's my number, impressive!\n")
goto goodbye goto goodbye

View File

@ -8,18 +8,18 @@
c64scr.print_string("Let's play a number guessing game!\n") c64scr.print_string("Let's play a number guessing game!\n")
c64scr.print_string("Enter your name: ") c64scr.print_string("Enter your name: ")
vm_input_str(name) Y=c64scr.input_chars(name)
c64scr.print_string("\nHello, ") c64scr.print_string("\nHello, ")
c64scr.print_string(name) c64scr.print_string(name)
c64scr.print_string(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n") c64scr.print_string(".\nI am thinking of a number from 1 to 100! You'll have to guess it!\n")
for ubyte attempts_left in 10 to 1 step -1 { for ubyte attempts_left in 10 to 1 step -1 {
c64scr.print_string("\nYou have ") c64scr.print_string("\nYou have ")
vm_write_num(attempts_left) c64scr.print_byte_decimal(attempts_left)
c64scr.print_string(" guess") c64scr.print_string(" guess")
if attempts_left>1 c64scr.print_string("es") if attempts_left>1 c64scr.print_string("es")
c64scr.print_string(" left. What is your next guess? ") c64scr.print_string(" left. What is your next guess? ")
vm_input_str(guess) Y=c64scr.input_chars(guess)
ubyte guessednumber = str2ubyte(guess) ubyte guessednumber = str2ubyte(guess)
if guessednumber==secretnumber { if guessednumber==secretnumber {
c64scr.print_string("\nYou guessed it, impressive!\n") c64scr.print_string("\nYou guessed it, impressive!\n")
@ -35,7 +35,7 @@
} }
c64scr.print_string("\nToo bad! My number was: ") c64scr.print_string("\nToo bad! My number was: ")
vm_write_num(secretnumber) c64scr.print_byte_decimal(secretnumber)
c64scr.print_string(".\n") c64scr.print_string(".\n")
return return
} }

View File

@ -1,63 +1,11 @@
%output raw
%launcher none
%import c64utils %import c64utils
%option enable_floats
~ main {
sub start() {
; memory ubyte[40] firstScreenLine = $0400
; word ww=333
;
; Y=33
;
; if(Y>3) {
; A=99
; } else {
; A=100
; }
;
; if(ww>33) {
; A=99
; } else {
; A=100
; }
;
; for ubyte c in 10 to 30 {
; firstScreenLine[c] = c
; }
ubyte bv = 99
word wv = 14443
float fv = 3.14
memory ubyte mb = $c000
memory word mw = $c100
memory float mf = $c200
memory ubyte[10] mba = $d000
memory word[10] mwa = $d100
memory float[10] mfa = $d200
memory str mstr = $d300
memory str_p mstrp = $d300
memory str_s mstrs = $d300
memory str_ps mstrps = $d300
mb = 5
mb = Y
mb = bv
mw = 22334
mw = wv
mf = 4.45
mf = fv
mba[9] = 5
mba[9] = Y
mba[9] = bv
mwa[9] = 22334
mwa[9] = wv
mfa[9] = 5.667
mfa[9] = fv
return
}
~ main {
memory ubyte[40*25] Screen = $0400
sub start() {
A, Y = c64flt.GETADRAY()
}
} }

View File

@ -413,7 +413,7 @@ class AstChecker(private val namespace: INameScope,
} }
} }
else else
checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.value, assignment.position) checkAssignmentCompatible(targetDatatype, sourceDatatype, assignment.value, assignment.targets, assignment.position)
} }
} }
return assignment return assignment
@ -482,13 +482,13 @@ class AstChecker(private val namespace: INameScope,
when(decl.datatype) { when(decl.datatype) {
DataType.ARRAY_B, DataType.ARRAY_UB -> DataType.ARRAY_B, DataType.ARRAY_UB ->
if(arraySize > 256) if(arraySize > 256)
err("byte arrayspec length must be 1-256") err("byte array length must be 1-256")
DataType.ARRAY_W, DataType.ARRAY_UW -> DataType.ARRAY_W, DataType.ARRAY_UW ->
if(arraySize > 128) if(arraySize > 128)
err("word arrayspec length must be 1-128") err("word array length must be 1-128")
DataType.ARRAY_F -> DataType.ARRAY_F ->
if(arraySize > 51) if(arraySize > 51)
err("float arrayspec length must be 1-51") err("float array length must be 1-51")
else -> {} else -> {}
} }
} }
@ -891,13 +891,13 @@ class AstChecker(private val namespace: INameScope,
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
if(arraySpecSize!=null && arraySpecSize>0) { if(arraySpecSize!=null && arraySpecSize>0) {
if(arraySpecSize<1 || arraySpecSize>256) if(arraySpecSize<1 || arraySpecSize>256)
return err("byte arrayspec length must be 1-256") return err("byte array length must be 1-256")
val constX = arrayspec.x.constValue(namespace, heap) val constX = arrayspec.x.constValue(namespace, heap)
if(constX?.asIntegerValue==null) if(constX?.asIntegerValue==null)
return err("arrayspec size specifier must be constant integer value") return err("array size specifier must be constant integer value")
val expectedSize = constX.asIntegerValue val expectedSize = constX.asIntegerValue
if (arraySize != expectedSize) if (arraySize != expectedSize)
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)") return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
return true return true
} }
return err("invalid byte array size, must be 1-256") return err("invalid byte array size, must be 1-256")
@ -911,18 +911,18 @@ class AstChecker(private val namespace: INameScope,
val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize val arraySize = value.arrayvalue?.size ?: heap.get(value.heapId!!).arraysize
if(arraySpecSize!=null && arraySpecSize>0) { if(arraySpecSize!=null && arraySpecSize>0) {
if(arraySpecSize<1 || arraySpecSize>128) if(arraySpecSize<1 || arraySpecSize>128)
return err("word arrayspec length must be 1-128") return err("word array length must be 1-128")
val constX = arrayspec.x.constValue(namespace, heap) val constX = arrayspec.x.constValue(namespace, heap)
if(constX?.asIntegerValue==null) if(constX?.asIntegerValue==null)
return err("arrayspec size specifier must be constant integer value") return err("array size specifier must be constant integer value")
val expectedSize = constX.asIntegerValue val expectedSize = constX.asIntegerValue
if (arraySize != expectedSize) if (arraySize != expectedSize)
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)") return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
return true return true
} }
return err("invalid word arrayspec size, must be 1-128") return err("invalid word array size, must be 1-128")
} }
return err("invalid word arrayspec initialization value ${value.type}, expected $targetDt") return err("invalid word array initialization value ${value.type}, expected $targetDt")
} }
DataType.ARRAY_F -> { DataType.ARRAY_F -> {
// value may be either a single float, or a float arrayspec // value may be either a single float, or a float arrayspec
@ -931,15 +931,15 @@ class AstChecker(private val namespace: INameScope,
val arraySpecSize = arrayspec.size() val arraySpecSize = arrayspec.size()
if(arraySpecSize!=null && arraySpecSize>0) { if(arraySpecSize!=null && arraySpecSize>0) {
if(arraySpecSize < 1 || arraySpecSize>51) if(arraySpecSize < 1 || arraySpecSize>51)
return err("float arrayspec length must be 1-51") return err("float array length must be 1-51")
val constX = arrayspec.x.constValue(namespace, heap) val constX = arrayspec.x.constValue(namespace, heap)
if(constX?.asIntegerValue==null) if(constX?.asIntegerValue==null)
return err("arrayspec size specifier must be constant integer value") return err("array size specifier must be constant integer value")
val expectedSize = constX.asIntegerValue val expectedSize = constX.asIntegerValue
if (arraySize != expectedSize) if (arraySize != expectedSize)
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)") return err("initializer array size mismatch (expecting $expectedSize, got $arraySize)")
} else } else
return err("invalid float arrayspec size, must be 1-51") return err("invalid float array size, must be 1-51")
// check if the floating point values are all within range // check if the floating point values are all within range
val doubles = if(value.arrayvalue!=null) val doubles = if(value.arrayvalue!=null)
@ -950,7 +950,7 @@ class AstChecker(private val namespace: INameScope,
return err("floating point value overflow") return err("floating point value overflow")
return true return true
} }
return err("invalid float arrayspec initialization value ${value.type}, expected $targetDt") return err("invalid float array initialization value ${value.type}, expected $targetDt")
} }
} }
return true return true
@ -959,6 +959,7 @@ class AstChecker(private val namespace: INameScope,
private fun checkAssignmentCompatible(targetDatatype: DataType, private fun checkAssignmentCompatible(targetDatatype: DataType,
sourceDatatype: DataType, sourceDatatype: DataType,
sourceValue: IExpression, sourceValue: IExpression,
assignTargets: List<AssignTarget>,
position: Position) : Boolean { position: Position) : Boolean {
if(sourceValue is RangeExpr) if(sourceValue is RangeExpr)
@ -980,8 +981,12 @@ class AstChecker(private val namespace: INameScope,
if(result) if(result)
return true return true
if((sourceDatatype==DataType.UWORD || sourceDatatype==DataType.WORD) && (targetDatatype==DataType.UBYTE || targetDatatype==DataType.BYTE)) if((sourceDatatype==DataType.UWORD || sourceDatatype==DataType.WORD) && (targetDatatype==DataType.UBYTE || targetDatatype==DataType.BYTE)) {
checkResult.add(ExpressionError("cannot assign word to byte, use msb() or lsb()?", position)) if(assignTargets.size==2 && assignTargets[0].register!=null && assignTargets[1].register!=null)
return true // for asm subroutine calls that return a (U)WORD that's going to be stored into two BYTES (registers), we make an exception.
else
checkResult.add(ExpressionError("cannot assign word to byte, use msb() or lsb()?", position))
}
else if(sourceDatatype==DataType.FLOAT && targetDatatype in IntegerDatatypes) else if(sourceDatatype==DataType.FLOAT && targetDatatype in IntegerDatatypes)
checkResult.add(ExpressionError("cannot assign float to ${targetDatatype.toString().toLowerCase()}; possible loss of precision. Suggestion: round the value or revert to integer arithmetic", position)) checkResult.add(ExpressionError("cannot assign float to ${targetDatatype.toString().toLowerCase()}; possible loss of precision. Suggestion: round the value or revert to integer arithmetic", position))
else else

View File

@ -21,7 +21,7 @@ abstract class Zeropage(private val options: CompilationOptions) {
DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! DataType.UBYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
DataType.UWORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2 DataType.UWORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5 DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5
else -> throw CompilerException("arrayspec can only be of byte, word, float") else -> throw CompilerException("array can only be of byte, word, float")
} }
} else { } else {
when (vardecl.datatype) { when (vardecl.datatype) {

View File

@ -274,8 +274,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
} }
currentBlock.variables[scopedname] = value currentBlock.variables[scopedname] = value
} }
VarDeclType.CONST -> {} // constants are all folded away VarDeclType.MEMORY, VarDeclType.CONST -> {
VarDeclType.MEMORY -> { // note that constants are all folded away, but assembly code may still refer to them
val lv = decl.value as LiteralValue val lv = decl.value as LiteralValue
if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE) if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE)
throw CompilerException("expected integer memory address $lv") throw CompilerException("expected integer memory address $lv")

View File

@ -619,10 +619,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
Opcode.INV_WORD -> { Opcode.INV_WORD -> {
""" """
lda ${(ESTACK_LO + 1).toHex()},x lda ${(ESTACK_LO+1).toHex()},x
eor #255 eor #255
sta ${(ESTACK_LO+1).toHex()},x sta ${(ESTACK_LO+1).toHex()},x
lda ${(ESTACK_HI + 1).toHex()},x lda ${(ESTACK_HI+1).toHex()},x
eor #255 eor #255
sta ${(ESTACK_HI+1).toHex()},x sta ${(ESTACK_HI+1).toHex()},x
""" """
@ -732,11 +732,6 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
Opcode.MUL_W -> " jsr prog8_lib.mul_w" Opcode.MUL_W -> " jsr prog8_lib.mul_w"
Opcode.MUL_UW -> " jsr prog8_lib.mul_uw" Opcode.MUL_UW -> " jsr prog8_lib.mul_uw"
Opcode.MUL_F -> " jsr prog8_lib.mul_f" Opcode.MUL_F -> " jsr prog8_lib.mul_f"
Opcode.LESS_UB -> " jsr prog8_lib.less_ub"
Opcode.LESS_B -> " jsr prog8_lib.less_b"
Opcode.LESS_UW -> " jsr prog8_lib.less_uw"
Opcode.LESS_W -> " jsr prog8_lib.less_w"
Opcode.LESS_F -> " jsr prog8_lib.less_f"
Opcode.AND_BYTE -> { Opcode.AND_BYTE -> {
""" """
@ -754,6 +749,39 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
sta ${(ESTACK_LO + 1).toHex()},x sta ${(ESTACK_LO + 1).toHex()},x
""" """
} }
Opcode.REMAINDER_B -> " jsr prog8_lib.remainder_b"
Opcode.REMAINDER_UB -> " jsr prog8_lib.remainder_ub"
Opcode.REMAINDER_W -> " jsr prog8_lib.remainder_w"
Opcode.REMAINDER_UW -> " jsr prog8_lib.remainder_uw"
Opcode.REMAINDER_F -> " jsr prog8_lib.remainder_f"
Opcode.GREATER_B -> " jsr prog8_lib.greater_b"
Opcode.GREATER_UB -> " jsr prog8_lib.greater_ub"
Opcode.GREATER_W -> " jsr prog8_lib.greater_w"
Opcode.GREATER_UW -> " jsr prog8_lib.greater_uw"
Opcode.GREATER_F -> " jsr prog8_lib.greater_f"
Opcode.GREATEREQ_B -> " jsr prog8_lib.greatereq_b"
Opcode.GREATEREQ_UB -> " jsr prog8_lib.greatereq_ub"
Opcode.GREATEREQ_W -> " jsr prog8_lib.greatereq_w"
Opcode.GREATEREQ_UW -> " jsr prog8_lib.greatereq_uw"
Opcode.GREATEREQ_F -> " jsr prog8_lib.greatereq_f"
Opcode.EQUAL_BYTE -> " jsr prog8_lib.equal_b"
Opcode.EQUAL_WORD -> " jsr prog8_lib.equal_w"
Opcode.EQUAL_F -> " jsr prog8_lib.equal_f"
Opcode.LESS_UB -> " jsr prog8_lib.less_ub"
Opcode.LESS_B -> " jsr prog8_lib.less_b"
Opcode.LESS_UW -> " jsr prog8_lib.less_uw"
Opcode.LESS_W -> " jsr prog8_lib.less_w"
Opcode.LESS_F -> " jsr prog8_lib.less_f"
Opcode.LESSEQ_UB -> " jsr prog8_lib.lesseq_ub"
Opcode.LESSEQ_B -> " jsr prog8_lib.lesseq_b"
Opcode.LESSEQ_UW -> " jsr prog8_lib.lesseq_uw"
Opcode.LESSEQ_W -> " jsr prog8_lib.lesseq_w"
Opcode.LESSEQ_F -> " jsr prog8_lib.lesseq_f"
else -> null else -> null
} }
@ -830,6 +858,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
private fun sameConstantIndexedVarOperation(variable: String, index: Int, ins: Instruction): AsmFragment? { private fun sameConstantIndexedVarOperation(variable: String, index: Int, ins: Instruction): AsmFragment? {
// an in place operation that consists of a push-value / op / push-index-value / pop-into-indexed-var
return when(ins.opcode) { return when(ins.opcode) {
Opcode.SHL_BYTE -> AsmFragment(" asl $variable+$index", 8) Opcode.SHL_BYTE -> AsmFragment(" asl $variable+$index", 8)
Opcode.SHR_BYTE -> AsmFragment(" lsr $variable+$index", 8) Opcode.SHR_BYTE -> AsmFragment(" lsr $variable+$index", 8)
@ -848,6 +877,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
private fun sameIndexedVarOperation(variable: String, indexVar: String, ins: Instruction): AsmFragment? { private fun sameIndexedVarOperation(variable: String, indexVar: String, ins: Instruction): AsmFragment? {
// an in place operation that consists of a push-value / op / push-index-var / pop-into-indexed-var
val saveX = " stx ${C64Zeropage.SCRATCH_B1} |" val saveX = " stx ${C64Zeropage.SCRATCH_B1} |"
val restoreX = " | ldx ${C64Zeropage.SCRATCH_B1}" val restoreX = " | ldx ${C64Zeropage.SCRATCH_B1}"
val loadXWord: String val loadXWord: String
@ -891,6 +921,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
private fun sameMemOperation(address: Int, ins: Instruction): AsmFragment? { private fun sameMemOperation(address: Int, ins: Instruction): AsmFragment? {
// an in place operation that consists of a push-mem / op / pop-mem sequence
val addr = address.toHex() val addr = address.toHex()
val addrHi = (address+1).toHex() val addrHi = (address+1).toHex()
return when(ins.opcode) { return when(ins.opcode) {
@ -911,6 +942,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
} }
private fun sameVarOperation(variable: String, ins: Instruction): AsmFragment? { private fun sameVarOperation(variable: String, ins: Instruction): AsmFragment? {
// an in place operation that consists of a push-var / op / pop-var
return when(ins.opcode) { return when(ins.opcode) {
Opcode.SHL_BYTE -> { Opcode.SHL_BYTE -> {
when (variable) { when (variable) {
@ -2705,9 +2737,28 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// push msb(word var) // push msb(word var)
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB)) { segment -> AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.MSB)) { segment ->
" lda #>${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex " " lda #>${segment[0].callLabel} | sta ${ESTACK_LO.toHex()},x | dex "
},
// set a register pair to a certain memory address (of a variable)
AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGAX_WORD)) { segment ->
" lda #<${segment[0].callLabel} | ldx #>${segment[0].callLabel} "
},
AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGAY_WORD)) { segment ->
" lda #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} "
},
AsmPattern(listOf(Opcode.PUSH_ADDR_HEAPVAR, Opcode.POP_REGXY_WORD)) { segment ->
" ldx #<${segment[0].callLabel} | ldy #>${segment[0].callLabel} "
},
// set a register pair to a certain memory address (of a literal string value)
AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGAX_WORD)) { segment ->
TODO("$segment")
},
AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGAY_WORD)) { segment ->
TODO("$segment")
},
AsmPattern(listOf(Opcode.PUSH_ADDR_STR, Opcode.POP_REGXY_WORD)) { segment ->
TODO("$segment")
} }
) )
} }

View File

@ -648,7 +648,7 @@ asmsub print_pstring (text: str_p @ XY) -> clobbers(A,X) -> (ubyte @ Y) {
asmsub print_byte_decimal0 (value: ubyte @ A) -> clobbers(A,X,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) ; ---- print the byte in A in decimal form, with left padding 0s (3 positions total)
%asm {{ %asm {{
jsr byte2decimal jsr c64utils.byte2decimal
pha pha
tya tya
jsr c64.CHROUT jsr c64.CHROUT
@ -663,7 +663,7 @@ asmsub print_byte_decimal0 (value: ubyte @ A) -> clobbers(A,X,Y) -> () {
asmsub print_byte_decimal (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 ; ---- print the byte in A in decimal form, without left padding 0s
%asm {{ %asm {{
jsr byte2decimal jsr c64utils.byte2decimal
pha pha
cpy #'0' cpy #'0'
bne _print_hundreds bne _print_hundreds
@ -689,7 +689,7 @@ asmsub print_byte_hex (prefix: ubyte @ Pc, value: ubyte @ A) -> clobbers(A,X,Y
lda #'$' lda #'$'
jsr c64.CHROUT jsr c64.CHROUT
pla pla
+ jsr byte2hex + jsr c64utils.byte2hex
txa txa
jsr c64.CHROUT jsr c64.CHROUT
tya tya
@ -716,16 +716,16 @@ 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) ; ---- print the (unsigned) word in X/Y in decimal form, with left padding 0s (5 positions total)
; @todo shorter in loop form? ; @todo shorter in loop form?
%asm {{ %asm {{
jsr word2decimal jsr c64utils.word2decimal
lda word2decimal_output lda c64utils.word2decimal_output
jsr c64.CHROUT jsr c64.CHROUT
lda word2decimal_output+1 lda c64utils.word2decimal_output+1
jsr c64.CHROUT jsr c64.CHROUT
lda word2decimal_output+2 lda c64utils.word2decimal_output+2
jsr c64.CHROUT jsr c64.CHROUT
lda word2decimal_output+3 lda c64utils.word2decimal_output+3
jsr c64.CHROUT jsr c64.CHROUT
lda word2decimal_output+4 lda c64utils.word2decimal_output+4
jmp c64.CHROUT jmp c64.CHROUT
}} }}
} }
@ -734,27 +734,27 @@ asmsub print_word_decimal0 (dataword: uword @ XY) -> clobbers(A,X,Y) -> () {
asmsub print_word_decimal (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 ; ---- print the word in X/Y in decimal form, without left padding 0s
%asm {{ %asm {{
jsr word2decimal jsr c64utils.word2decimal
ldy #0 ldy #0
lda word2decimal_output lda c64utils.word2decimal_output
cmp #'0' cmp #'0'
bne _pr_decimal bne _pr_decimal
iny iny
lda word2decimal_output+1 lda c64utils.word2decimal_output+1
cmp #'0' cmp #'0'
bne _pr_decimal bne _pr_decimal
iny iny
lda word2decimal_output+2 lda c64utils.word2decimal_output+2
cmp #'0' cmp #'0'
bne _pr_decimal bne _pr_decimal
iny iny
lda word2decimal_output+3 lda c64utils.word2decimal_output+3
cmp #'0' cmp #'0'
bne _pr_decimal bne _pr_decimal
iny iny
_pr_decimal _pr_decimal
lda word2decimal_output,y lda c64utils.word2decimal_output,y
jsr c64.CHROUT jsr c64.CHROUT
iny iny
cpy #5 cpy #5

View File

@ -82,15 +82,6 @@ mul_f
neg_f neg_f
rts rts
less_ub
rts
less_b
rts
less_f
rts
add_w add_w
rts ; @todo inline? rts ; @todo inline?
@ -120,7 +111,92 @@ div_w
div_uw div_uw
rts rts
remainder_b
rts
remainder_ub
rts
remainder_w
rts
remainder_uw
rts
remainder_f
rts
equal_ub
rts
equal_b
rts
equal_w
rts
equal_uw
rts
equal_f
rts
less_ub
rts
less_b
rts
less_w
rts
less_uw
rts
less_f
rts
lesseq_ub
rts
lesseq_b
rts
lesseq_w
rts
lesseq_uw
rts
lesseq_f
rts
greater_ub
rts
greater_b
rts
greater_w
rts
greater_uw
rts
greater_f
rts
greatereq_ub
rts
greatereq_b
rts
greatereq_w
rts
greatereq_uw
rts
greatereq_f
rts
func_sin func_sin
rts rts
func_cos func_cos