mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 08:29:25 +00:00
more asm, constants now also outputted in asm source
This commit is contained in:
parent
08224d5367
commit
0c64d7ffe5
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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")
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user