mirror of
https://github.com/irmen/prog8.git
synced 2024-09-10 09:54:32 +00:00
more forloop asm
This commit is contained in:
parent
9edc92ec29
commit
5e854c2cf8
@ -43,7 +43,7 @@ dependencies {
|
|||||||
compileKotlin {
|
compileKotlin {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
verbose = true
|
// verbose = true
|
||||||
// freeCompilerArgs += "-XXLanguage:+NewInference"
|
// freeCompilerArgs += "-XXLanguage:+NewInference"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,14 @@ import prog8.ast.expressions.RangeExpr
|
|||||||
import prog8.ast.statements.AssignTarget
|
import prog8.ast.statements.AssignTarget
|
||||||
import prog8.ast.statements.Assignment
|
import prog8.ast.statements.Assignment
|
||||||
import prog8.ast.statements.ForLoop
|
import prog8.ast.statements.ForLoop
|
||||||
import prog8.compiler.target.c64.MachineDefinition
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX
|
||||||
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX
|
||||||
|
import prog8.compiler.target.c64.MachineDefinition.ESTACK_HI_PLUS1_HEX
|
||||||
import prog8.compiler.toHex
|
import prog8.compiler.toHex
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
|
// todo choose more efficient comparisons to avoid needless lda's
|
||||||
|
|
||||||
|
|
||||||
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
|
|
||||||
@ -25,8 +29,6 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
|
|||||||
if(range==null) {
|
if(range==null) {
|
||||||
translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), stmt.iterable as RangeExpr)
|
translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), stmt.iterable as RangeExpr)
|
||||||
} else {
|
} else {
|
||||||
if (range.isEmpty())
|
|
||||||
throw AssemblyError("empty range")
|
|
||||||
translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), range)
|
translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,14 +43,16 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
|
|||||||
val loopLabel = asmgen.makeLabel("for_loop")
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
val endLabel = asmgen.makeLabel("for_end")
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
val continueLabel = asmgen.makeLabel("for_continue")
|
val continueLabel = asmgen.makeLabel("for_continue")
|
||||||
val counterLabel = asmgen.makeLabel("for_counter")
|
|
||||||
asmgen.loopEndLabels.push(endLabel)
|
asmgen.loopEndLabels.push(endLabel)
|
||||||
asmgen.loopContinueLabels.push(continueLabel)
|
asmgen.loopContinueLabels.push(continueLabel)
|
||||||
val stepsize=range.step.constValue(program)?.number
|
val stepsize=range.step.constValue(program)!!.number.toInt()
|
||||||
when (stepsize) {
|
|
||||||
1 -> {
|
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||||
|
if (stepsize==1 || stepsize==-1) {
|
||||||
|
|
||||||
|
// bytes, step 1 or -1
|
||||||
|
|
||||||
|
val incdec = if(stepsize==1) "inc" else "dec"
|
||||||
if (stmt.loopRegister != null) {
|
if (stmt.loopRegister != null) {
|
||||||
// loop register over range
|
// loop register over range
|
||||||
if(stmt.loopRegister!= Register.A)
|
if(stmt.loopRegister!= Register.A)
|
||||||
@ -57,23 +61,17 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
|
|||||||
asmgen.translateExpression(range.from)
|
asmgen.translateExpression(range.from)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
inx
|
inx
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX},x
|
lda ${ESTACK_LO_HEX},x
|
||||||
sta $loopLabel+1
|
sta $loopLabel+1
|
||||||
inx
|
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX},x
|
|
||||||
sec
|
|
||||||
sbc $loopLabel+1
|
|
||||||
adc #0
|
|
||||||
sta $counterLabel
|
|
||||||
$loopLabel lda #0 ; modified""")
|
$loopLabel lda #0 ; modified""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel dec $counterLabel
|
$continueLabel lda $loopLabel+1
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
beq $endLabel
|
beq $endLabel
|
||||||
inc $loopLabel+1
|
$incdec $loopLabel+1
|
||||||
jmp $loopLabel
|
jmp $loopLabel
|
||||||
$counterLabel .byte 0
|
$endLabel inx""")
|
||||||
$endLabel""")
|
|
||||||
} else {
|
} else {
|
||||||
// loop over byte range via loopvar
|
// loop over byte range via loopvar
|
||||||
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
||||||
@ -81,28 +79,96 @@ $endLabel""")
|
|||||||
asmgen.translateExpression(range.from)
|
asmgen.translateExpression(range.from)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
inx
|
inx
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX},x
|
lda ${ESTACK_LO_HEX},x
|
||||||
sta $varname
|
sta $varname
|
||||||
inx
|
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX},x
|
|
||||||
sec
|
|
||||||
sbc $varname
|
|
||||||
adc #0
|
|
||||||
sta $counterLabel
|
|
||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel dec $counterLabel
|
$continueLabel lda $varname
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
beq $endLabel
|
beq $endLabel
|
||||||
inc $varname
|
$incdec $varname
|
||||||
jmp $loopLabel
|
jmp $loopLabel
|
||||||
$counterLabel .byte 0
|
$endLabel inx""")
|
||||||
$endLabel""")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
else {
|
||||||
|
|
||||||
|
// bytes, step >= 2 or <= -2
|
||||||
|
|
||||||
|
if (stmt.loopRegister != null) {
|
||||||
|
// loop register over range
|
||||||
|
if(stmt.loopRegister!= Register.A)
|
||||||
|
throw AssemblyError("can only use A")
|
||||||
|
asmgen.translateExpression(range.to)
|
||||||
|
asmgen.translateExpression(range.from)
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
lda ${ESTACK_LO_HEX},x
|
||||||
|
sta $loopLabel+1
|
||||||
|
$loopLabel lda #0 ; modified""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
$continueLabel lda $loopLabel+1""")
|
||||||
|
if(stepsize>0) {
|
||||||
|
asmgen.out("""
|
||||||
|
clc
|
||||||
|
adc #$stepsize
|
||||||
|
sta $loopLabel+1
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
bcc $loopLabel
|
||||||
|
beq $loopLabel""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
sec
|
||||||
|
sbc #${stepsize.absoluteValue}
|
||||||
|
sta $loopLabel+1
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
bcs $loopLabel""")
|
||||||
|
}
|
||||||
|
asmgen.out("""
|
||||||
|
$endLabel inx""")
|
||||||
|
} else {
|
||||||
|
// loop over byte range via loopvar
|
||||||
|
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
||||||
|
asmgen.translateExpression(range.to)
|
||||||
|
asmgen.translateExpression(range.from)
|
||||||
|
asmgen.out("""
|
||||||
|
inx
|
||||||
|
lda ${ESTACK_LO_HEX},x
|
||||||
|
sta $varname
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
$continueLabel lda $varname""")
|
||||||
|
if(stepsize>0) {
|
||||||
|
asmgen.out("""
|
||||||
|
clc
|
||||||
|
adc #$stepsize
|
||||||
|
sta $varname
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
bcc $loopLabel
|
||||||
|
beq $loopLabel""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
sec
|
||||||
|
sbc #${stepsize.absoluteValue}
|
||||||
|
sta $varname
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
bcs $loopLabel""")
|
||||||
|
}
|
||||||
|
asmgen.out("""
|
||||||
|
$endLabel inx""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
||||||
|
when {
|
||||||
|
|
||||||
|
// words, step 1 or -1
|
||||||
|
|
||||||
|
stepsize == 1 || stepsize == -1 -> {
|
||||||
asmgen.translateExpression(range.to)
|
asmgen.translateExpression(range.to)
|
||||||
asmgen.out(" inc ${MachineDefinition.ESTACK_LO_HEX}+1,x | bne + | inc ${MachineDefinition.ESTACK_HI_HEX}+1,x |+ ")
|
|
||||||
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
||||||
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
|
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
|
||||||
null, range.from, range.position)
|
null, range.from, range.position)
|
||||||
@ -111,81 +177,34 @@ $endLabel""")
|
|||||||
asmgen.out(loopLabel)
|
asmgen.out(loopLabel)
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
inc $varname
|
lda $varname+1
|
||||||
|
cmp $ESTACK_HI_PLUS1_HEX,x
|
||||||
|
bne +
|
||||||
|
lda $varname
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
beq $endLabel""")
|
||||||
|
if(stepsize==1) {
|
||||||
|
asmgen.out("""
|
||||||
|
+ inc $varname
|
||||||
bne +
|
bne +
|
||||||
inc $varname+1
|
inc $varname+1
|
||||||
+ lda ${MachineDefinition.ESTACK_HI_HEX}+1,x
|
""")
|
||||||
cmp $varname+1
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
+ lda $varname
|
||||||
bne +
|
bne +
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
|
dec $varname+1
|
||||||
cmp $varname
|
+ dec $varname""")
|
||||||
beq $endLabel
|
}
|
||||||
|
asmgen.out("""
|
||||||
+ jmp $loopLabel
|
+ jmp $loopLabel
|
||||||
$endLabel inx""")
|
$endLabel inx""")
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("range expression can only be byte or word")
|
stepsize > 0 -> {
|
||||||
}
|
|
||||||
}
|
// (u)words, step >= 2
|
||||||
-1 -> {
|
|
||||||
when(iterableDt){
|
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
|
||||||
if (stmt.loopRegister != null) {
|
|
||||||
// loop register over range
|
|
||||||
if(stmt.loopRegister!= Register.A)
|
|
||||||
throw AssemblyError("can only use A")
|
|
||||||
asmgen.translateExpression(range.from)
|
|
||||||
asmgen.translateExpression(range.to)
|
asmgen.translateExpression(range.to)
|
||||||
asmgen.out("""
|
|
||||||
inx
|
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
|
|
||||||
sta $loopLabel+1
|
|
||||||
sec
|
|
||||||
sbc ${MachineDefinition.ESTACK_LO_HEX},x
|
|
||||||
adc #0
|
|
||||||
sta $counterLabel
|
|
||||||
inx
|
|
||||||
$loopLabel lda #0 ; modified""")
|
|
||||||
asmgen.translate(stmt.body)
|
|
||||||
asmgen.out("""
|
|
||||||
$continueLabel dec $counterLabel
|
|
||||||
beq $endLabel
|
|
||||||
dec $loopLabel+1
|
|
||||||
jmp $loopLabel
|
|
||||||
$counterLabel .byte 0
|
|
||||||
$endLabel""")
|
|
||||||
} else {
|
|
||||||
// loop over byte range via loopvar
|
|
||||||
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
|
||||||
asmgen.translateExpression(range.from)
|
|
||||||
asmgen.translateExpression(range.to)
|
|
||||||
asmgen.out("""
|
|
||||||
inx
|
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
|
|
||||||
sta $varname
|
|
||||||
sec
|
|
||||||
sbc ${MachineDefinition.ESTACK_LO_HEX},x
|
|
||||||
adc #0
|
|
||||||
sta $counterLabel
|
|
||||||
inx
|
|
||||||
$loopLabel""")
|
|
||||||
asmgen.translate(stmt.body)
|
|
||||||
asmgen.out("""
|
|
||||||
$continueLabel dec $counterLabel
|
|
||||||
beq $endLabel
|
|
||||||
dec $varname
|
|
||||||
jmp $loopLabel
|
|
||||||
$counterLabel .byte 0
|
|
||||||
$endLabel""")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
|
||||||
asmgen.translateExpression(range.to)
|
|
||||||
asmgen.out("""
|
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
|
|
||||||
bne +
|
|
||||||
dec ${MachineDefinition.ESTACK_HI_HEX}+1,x
|
|
||||||
+ dec ${MachineDefinition.ESTACK_LO_HEX}+1,x
|
|
||||||
""")
|
|
||||||
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
||||||
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
|
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
|
||||||
null, range.from, range.position)
|
null, range.from, range.position)
|
||||||
@ -193,29 +212,97 @@ $endLabel""")
|
|||||||
asmgen.translate(assignLoopvar)
|
asmgen.translate(assignLoopvar)
|
||||||
asmgen.out(loopLabel)
|
asmgen.out(loopLabel)
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
|
|
||||||
|
if (iterableDt == DataType.ARRAY_UW) {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
lda $varname
|
lda $varname
|
||||||
bne +
|
clc
|
||||||
dec $varname+1
|
adc #<$stepsize
|
||||||
+ dec $varname
|
sta $varname
|
||||||
lda ${MachineDefinition.ESTACK_HI_HEX}+1,x
|
lda $varname+1
|
||||||
|
adc #>$stepsize
|
||||||
|
sta $varname+1
|
||||||
|
lda $ESTACK_HI_PLUS1_HEX,x
|
||||||
cmp $varname+1
|
cmp $varname+1
|
||||||
bne +
|
bcc $endLabel
|
||||||
lda ${MachineDefinition.ESTACK_LO_HEX}+1,x
|
bne $loopLabel
|
||||||
|
lda $varname
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
bcc $endLabel
|
||||||
|
bcs $loopLabel
|
||||||
|
$endLabel inx""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
clc
|
||||||
|
adc #<$stepsize
|
||||||
|
sta $varname
|
||||||
|
lda $varname+1
|
||||||
|
adc #>$stepsize
|
||||||
|
sta $varname+1
|
||||||
|
lda $ESTACK_LO_PLUS1_HEX,x
|
||||||
cmp $varname
|
cmp $varname
|
||||||
beq $endLabel
|
lda $ESTACK_HI_PLUS1_HEX,x
|
||||||
+ jmp $loopLabel
|
sbc $varname+1
|
||||||
|
bvc +
|
||||||
|
eor #$80
|
||||||
|
+ bpl $loopLabel
|
||||||
$endLabel inx""")
|
$endLabel inx""")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
|
||||||
|
// (u)words, step <= -2
|
||||||
|
asmgen.translateExpression(range.to)
|
||||||
|
val varname = asmgen.asmIdentifierName(stmt.loopVar!!)
|
||||||
|
val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position),
|
||||||
|
null, range.from, range.position)
|
||||||
|
assignLoopvar.linkParents(stmt)
|
||||||
|
asmgen.translate(assignLoopvar)
|
||||||
|
asmgen.out(loopLabel)
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
|
||||||
|
if(iterableDt==DataType.ARRAY_UW) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
sec
|
||||||
|
sbc #<${stepsize.absoluteValue}
|
||||||
|
sta $varname
|
||||||
|
lda $varname+1
|
||||||
|
sbc #>${stepsize.absoluteValue}
|
||||||
|
sta $varname+1
|
||||||
|
cmp $ESTACK_HI_PLUS1_HEX,x
|
||||||
|
bcc $endLabel
|
||||||
|
bne $loopLabel
|
||||||
|
lda $varname
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
bcs $loopLabel
|
||||||
|
$endLabel inx""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
sec
|
||||||
|
sbc #<${stepsize.absoluteValue}
|
||||||
|
sta $varname
|
||||||
|
pha
|
||||||
|
lda $varname+1
|
||||||
|
sbc #>${stepsize.absoluteValue}
|
||||||
|
sta $varname+1
|
||||||
|
pla
|
||||||
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
|
lda $varname+1
|
||||||
|
sbc $ESTACK_HI_PLUS1_HEX,x
|
||||||
|
bvc +
|
||||||
|
eor #$80
|
||||||
|
+ bpl $loopLabel
|
||||||
|
$endLabel inx""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> throw AssemblyError("range expression can only be byte or word")
|
else -> throw AssemblyError("range expression can only be byte or word")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else -> when (iterableDt) {
|
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B -> TODO("non-const forloop bytes, step >1: $stepsize")
|
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> TODO("non-const forloop words, step >1: $stepsize")
|
|
||||||
else -> throw AssemblyError("range expression can only be byte or word")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asmgen.loopEndLabels.pop()
|
asmgen.loopEndLabels.pop()
|
||||||
asmgen.loopContinueLabels.pop()
|
asmgen.loopContinueLabels.pop()
|
||||||
}
|
}
|
||||||
@ -322,6 +409,8 @@ $endLabel""")
|
|||||||
|
|
||||||
private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) {
|
private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) {
|
||||||
// TODO: optimize loop code when the range is < 256 iterations, don't need a separate counter in such cases
|
// TODO: optimize loop code when the range is < 256 iterations, don't need a separate counter in such cases
|
||||||
|
if (range.isEmpty())
|
||||||
|
throw AssemblyError("empty range")
|
||||||
val loopLabel = asmgen.makeLabel("for_loop")
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
val endLabel = asmgen.makeLabel("for_end")
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
val continueLabel = asmgen.makeLabel("for_continue")
|
val continueLabel = asmgen.makeLabel("for_continue")
|
||||||
@ -544,11 +633,59 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
range.step >= 2 -> {
|
range.step >= 2 -> {
|
||||||
// word, step >= 2
|
// word, step >= 2
|
||||||
TODO("for, word, step>=2")
|
// note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence
|
||||||
|
val lastValue = range.last+range.step
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<${range.first}
|
||||||
|
ldy #>${range.first}
|
||||||
|
sta $varname
|
||||||
|
sty $varname+1
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
$continueLabel clc
|
||||||
|
lda $varname
|
||||||
|
adc #<${range.step}
|
||||||
|
sta $varname
|
||||||
|
lda $varname+1
|
||||||
|
adc #>${range.step}
|
||||||
|
sta $varname+1
|
||||||
|
lda $varname
|
||||||
|
cmp #<$lastValue
|
||||||
|
bne +
|
||||||
|
lda $varname+1
|
||||||
|
cmp #>$lastValue
|
||||||
|
beq $endLabel
|
||||||
|
+ jmp $loopLabel
|
||||||
|
$endLabel""")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// step <= -2
|
// step <= -2
|
||||||
TODO("for, word, step<=-2")
|
// note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence
|
||||||
|
val lastValue = range.last+range.step
|
||||||
|
asmgen.out("""
|
||||||
|
lda #<${range.first}
|
||||||
|
ldy #>${range.first}
|
||||||
|
sta $varname
|
||||||
|
sty $varname+1
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
$continueLabel sec
|
||||||
|
lda $varname
|
||||||
|
sbc #<${range.step.absoluteValue}
|
||||||
|
sta $varname
|
||||||
|
lda $varname+1
|
||||||
|
sbc #>${range.step.absoluteValue}
|
||||||
|
sta $varname+1
|
||||||
|
lda $varname
|
||||||
|
cmp #<$lastValue
|
||||||
|
bne +
|
||||||
|
lda $varname+1
|
||||||
|
cmp #>$lastValue
|
||||||
|
beq $endLabel
|
||||||
|
+ jmp $loopLabel
|
||||||
|
$endLabel""")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,39 @@ main {
|
|||||||
else
|
else
|
||||||
c64scr.print("error in -222>=-222!\n")
|
c64scr.print("error in -222>=-222!\n")
|
||||||
|
|
||||||
|
v1 = 1000
|
||||||
|
v2 = 1000
|
||||||
|
if v1==v2
|
||||||
|
c64scr.print("ok: 1000 == 1000\n")
|
||||||
|
else
|
||||||
|
c64scr.print("error in 1000==1000!\n")
|
||||||
|
|
||||||
|
if v1!=v2
|
||||||
|
c64scr.print("error in 1000!=1000!\n")
|
||||||
|
else
|
||||||
|
c64scr.print("ok: 1000 is not != 1000\n")
|
||||||
|
|
||||||
|
if v1<v2
|
||||||
|
c64scr.print("error in 1000<1000!\n")
|
||||||
|
else
|
||||||
|
c64scr.print("ok: 1000 is not < 1000\n")
|
||||||
|
|
||||||
|
if v1<=v2
|
||||||
|
c64scr.print("ok: 1000 <= 1000\n")
|
||||||
|
else
|
||||||
|
c64scr.print("error in 1000<=1000!\n")
|
||||||
|
|
||||||
|
if v1>v2
|
||||||
|
c64scr.print("error in 1000>1000!\n")
|
||||||
|
else
|
||||||
|
c64scr.print("ok: 1000 is not > 1000\n")
|
||||||
|
|
||||||
|
if v1>=v2
|
||||||
|
c64scr.print("ok: 1000 >= 1000\n")
|
||||||
|
else
|
||||||
|
c64scr.print("error in 1000>=1000!\n")
|
||||||
|
|
||||||
|
|
||||||
ubyte endX = X
|
ubyte endX = X
|
||||||
if endX == 255
|
if endX == 255
|
||||||
c64scr.print("stack x ok!\n")
|
c64scr.print("stack x ok!\n")
|
||||||
|
305
examples/test.p8
305
examples/test.p8
@ -1,90 +1,263 @@
|
|||||||
%import c64lib
|
|
||||||
%import c64utils
|
|
||||||
%import c64flt
|
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
; TODO implement asm generation for all loops here
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
str str1 = "irmen"
|
|
||||||
str str2 = "test"
|
|
||||||
str_s strs1 = "irmen"
|
|
||||||
str_s strs2 = "test"
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
str str1x = "irmen"
|
byte bvar
|
||||||
str str2x = "test"
|
ubyte var2
|
||||||
str_s strs1x = "irmen"
|
|
||||||
str_s strs2x = "test"
|
|
||||||
|
|
||||||
c64scr.print(str1)
|
ubyte[] barr = [22,33,44,55,66]
|
||||||
c64.CHROUT('\n')
|
word[] warr = [-111,222,-333,444]
|
||||||
c64scr.print(str2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print(str1x)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
c64scr.print(str2x)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
str1[0]='a'
|
; for A in "hello" {
|
||||||
str2[0]='a'
|
; c64scr.print_ub(A)
|
||||||
str1x[0]='a'
|
; c64.CHROUT(',')
|
||||||
str2x[0]='a'
|
; }
|
||||||
strs1x[0]='a'
|
; c64.CHROUT('\n')
|
||||||
strs2x[0]='a'
|
;
|
||||||
strs1[0]='a'
|
; for A in [1,3,5,99] {
|
||||||
strs2[0]='a'
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
c64scr.print(str1)
|
; }
|
||||||
c64.CHROUT('\n')
|
; c64.CHROUT('\n')
|
||||||
c64scr.print(str2)
|
;
|
||||||
c64.CHROUT('\n')
|
; for A in 10 to 20 {
|
||||||
c64scr.print(str1x)
|
; c64scr.print_ub(A)
|
||||||
c64.CHROUT('\n')
|
; c64.CHROUT(',')
|
||||||
c64scr.print(str2x)
|
; }
|
||||||
c64.CHROUT('\n')
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for A in 20 to 10 step -1 {
|
||||||
byte[] barr = [1,2,3]
|
; c64scr.print_ub(A)
|
||||||
word[] warr = [1000,2000,3000]
|
; c64.CHROUT(',')
|
||||||
float[] farr = [1.1, 2.2, 3.3]
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for A in 10 to 21 step 3 {
|
||||||
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for A in 24 to 10 step -3 {
|
||||||
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for A in barr {
|
||||||
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; ubyte cc
|
||||||
|
; for cc in "hello" {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for cc in [1,3,5,99] {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for cc in 10 to 20 {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for cc in 20 to 10 step -1 {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for cc in 10 to 21 step 3 {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for cc in 24 to 10 step -3 {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for cc in barr {
|
||||||
|
; c64scr.print_ub(cc)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; uword uw
|
||||||
|
; for uw in [1111, 2222, 3333] {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for ww in warr {
|
||||||
|
; c64scr.print_w(ww)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for uw in 1111 to 1117 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for uw in 2000 to 1995 step -1 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for uw in 1111 to 50000 step 4444 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
|
||||||
|
word endw1 = 999
|
||||||
|
uword enduw1 = 2600
|
||||||
|
word endw2 = -999
|
||||||
|
byte endb1 = 100
|
||||||
|
byte endb2 = -100
|
||||||
byte bb
|
byte bb
|
||||||
word ww
|
word ww
|
||||||
float ff
|
uword uw
|
||||||
for bb in barr {
|
ubyte ub
|
||||||
c64scr.print_b(bb)
|
ubyte ubb
|
||||||
c64.CHROUT(',')
|
|
||||||
}
|
; for A in 95 to endb1 step 1 {
|
||||||
c64.CHROUT('\n')
|
; c64scr.print_ub(A)
|
||||||
for ww in warr {
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for bb in 95 to endb1 step 1 {
|
||||||
|
; c64scr.print_b(bb)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for A in endb1 to 95 step -1 {
|
||||||
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for bb in -95 to endb2 step -1 {
|
||||||
|
; c64scr.print_b(bb)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for ww in 995 to endw1 step 1 {
|
||||||
|
; c64scr.print_w(ww)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for ww in -995 to endw2 step -1 {
|
||||||
|
; c64scr.print_w(ww)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for A in 90 to endb1 step 3 {
|
||||||
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for bb in 90 to endb1 step 3 {
|
||||||
|
; c64scr.print_b(bb)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; ubb = 10
|
||||||
|
; for A in 20 to ubb step -3 {
|
||||||
|
; c64scr.print_ub(A)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for bb in -90 to endb2 step -3 {
|
||||||
|
; c64scr.print_b(bb)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for uw in 999 to enduw1 step 500 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for uw in enduw1 to 999 step -500 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for ww in -999 to endw1 step 500 { ; TODO fix loop asm
|
||||||
c64scr.print_w(ww)
|
c64scr.print_w(ww)
|
||||||
c64.CHROUT(',')
|
c64.CHROUT(',')
|
||||||
}
|
}
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
for bb in 0 to len(farr)-1 {
|
|
||||||
c64flt.print_f(farr[bb])
|
|
||||||
c64.CHROUT(',')
|
|
||||||
}
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
barr[0] = 99
|
; for ww in 999 to endw2 step -500 {
|
||||||
warr[0] = 99
|
; c64scr.print_w(ww)
|
||||||
farr[0] = 99.9
|
; c64.CHROUT(',')
|
||||||
for bb in barr {
|
; }
|
||||||
c64scr.print_b(bb)
|
; c64.CHROUT('\n')
|
||||||
c64.CHROUT(',')
|
; c64.CHROUT('\n')
|
||||||
}
|
;
|
||||||
c64.CHROUT('\n')
|
; enduw1 = 2000
|
||||||
for ww in warr {
|
; for uw in 500 to enduw1 step 500 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
;
|
||||||
|
; for uw in enduw1 to 500 step -500 {
|
||||||
|
; c64scr.print_uw(uw)
|
||||||
|
; c64.CHROUT(',')
|
||||||
|
; }
|
||||||
|
; c64.CHROUT('\n')
|
||||||
|
|
||||||
|
endw1 = 1000
|
||||||
|
for ww in -1000 to endw1 step 500 { ; TODO fix loop asm
|
||||||
c64scr.print_w(ww)
|
c64scr.print_w(ww)
|
||||||
c64.CHROUT(',')
|
c64.CHROUT(',')
|
||||||
}
|
}
|
||||||
c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
for bb in 0 to len(farr)-1 {
|
|
||||||
c64flt.print_f(farr[bb])
|
for ww in 3000 to endw1 step -500 {
|
||||||
|
c64scr.print_w(ww)
|
||||||
c64.CHROUT(',')
|
c64.CHROUT(',')
|
||||||
}
|
}
|
||||||
}
|
c64.CHROUT('\n')
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
ubb=X
|
||||||
|
c64scr.print_ub(ubb)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,4 @@ org.gradle.parallel=true
|
|||||||
org.gradle.jvmargs=-Xmx2500M
|
org.gradle.jvmargs=-Xmx2500M
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
|
|
||||||
kotlinVersion=1.3.41
|
kotlinVersion=1.3.50
|
||||||
|
Loading…
Reference in New Issue
Block a user