mirror of
https://github.com/irmen/prog8.git
synced 2024-11-16 22:09:56 +00:00
rebuilding floating point stack evaluation (using cpu stack)
This commit is contained in:
parent
9f247901d4
commit
d5707b7bf3
@ -207,7 +207,8 @@ class AsmGen6502Internal (
|
||||
private val postincrdecrAsmGen = PostIncrDecrAsmGen(program, this)
|
||||
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
|
||||
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, this, allocator)
|
||||
private val anyExprGen = AnyExprAsmGen(this)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, this, anyExprGen, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
|
||||
|
||||
fun compileToAssembly(): IAssemblyProgram? {
|
||||
@ -3013,6 +3014,14 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun pushFAC1() {
|
||||
out(" jsr floats.pushFAC1")
|
||||
}
|
||||
|
||||
internal fun popFAC1() {
|
||||
out(" jsr floats.popFAC1")
|
||||
}
|
||||
|
||||
internal fun needAsaveForExpr(arg: PtExpression): Boolean =
|
||||
arg !is PtNumber && arg !is PtIdentifier && (arg !is PtMemoryByte || !arg.isSimple())
|
||||
|
||||
|
@ -0,0 +1,266 @@
|
||||
package prog8.codegen.cpu6502.assignment
|
||||
|
||||
import prog8.code.ast.PtBinaryExpression
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||
|
||||
//
|
||||
// This contains codegen for stack-based evaluation of binary expressions.
|
||||
// It uses the CPU stack so depth is limited.
|
||||
// It is called "as a last resort" if the optimized codegen path is unable
|
||||
// to come up with a special case of the expression.
|
||||
//
|
||||
internal class AnyExprAsmGen(
|
||||
private val asmgen: AsmGen6502Internal
|
||||
) {
|
||||
fun assignAnyExpressionUsingStack(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
when(expr.type) {
|
||||
in ByteDatatypes -> {
|
||||
if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes)
|
||||
return assignByteBinExpr(expr, assign)
|
||||
if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||
require(expr.operator in ComparisonOperators)
|
||||
TODO("words operands comparison -> byte")
|
||||
}
|
||||
if (expr.left.type==DataType.FLOAT && expr.right.type==DataType.FLOAT) {
|
||||
require(expr.operator in ComparisonOperators)
|
||||
return assignFloatBinExpr(expr, assign)
|
||||
}
|
||||
TODO("weird expr operand types")
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
require(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
|
||||
"both operands must be words"
|
||||
}
|
||||
return assignWordBinExpr(expr, assign)
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
require(expr.left.type==DataType.FLOAT && expr.right.type==DataType.FLOAT) {
|
||||
"both operands must be floats"
|
||||
}
|
||||
return assignFloatBinExpr(expr, assign)
|
||||
}
|
||||
else -> throw AssemblyError("weird expression type in assignment")
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignWordBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
when(expr.operator) {
|
||||
"+" -> {
|
||||
TODO("word + at ${expr.position}")
|
||||
}
|
||||
"-" -> {
|
||||
TODO("word - at ${expr.position}")
|
||||
}
|
||||
"*" -> {
|
||||
TODO("word * at ${expr.position}")
|
||||
}
|
||||
"/" -> {
|
||||
TODO("word / at ${expr.position}")
|
||||
}
|
||||
"<<" -> {
|
||||
TODO("word << at ${expr.position}")
|
||||
}
|
||||
">>" -> {
|
||||
TODO("word >> at ${expr.position}")
|
||||
}
|
||||
"%" -> {
|
||||
TODO("word % at ${expr.position}")
|
||||
}
|
||||
"&", "and" -> {
|
||||
TODO("word and at ${expr.position}")
|
||||
}
|
||||
"|", "or" -> {
|
||||
TODO("word or at ${expr.position}")
|
||||
}
|
||||
"^", "xor" -> {
|
||||
TODO("word xor at ${expr.position}")
|
||||
}
|
||||
"==" -> {
|
||||
TODO("word == at ${expr.position}")
|
||||
}
|
||||
"!=" -> {
|
||||
TODO("word != at ${expr.position}")
|
||||
}
|
||||
"<" -> {
|
||||
TODO("word < at ${expr.position}")
|
||||
}
|
||||
"<=" -> {
|
||||
TODO("word <= at ${expr.position}")
|
||||
}
|
||||
">" -> {
|
||||
TODO("word > at ${expr.position}")
|
||||
}
|
||||
">=" -> {
|
||||
TODO("word >= at ${expr.position}")
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignByteBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
when(expr.operator) {
|
||||
"+" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla | clc | adc P8ZP_SCRATCH_B1")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"-" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla | sec | sbc P8ZP_SCRATCH_B1")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"*" -> {
|
||||
TODO("byte * at ${expr.position}")
|
||||
}
|
||||
"/" -> {
|
||||
TODO("byte / at ${expr.position}")
|
||||
}
|
||||
"<<" -> {
|
||||
TODO("byte << at ${expr.position}")
|
||||
}
|
||||
">>" -> {
|
||||
TODO("byte >> at ${expr.position}")
|
||||
}
|
||||
"%" -> {
|
||||
TODO("byte % at ${expr.position}")
|
||||
}
|
||||
"&", "and" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla | and P8ZP_SCRATCH_B1")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"|", "or" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla | ora P8ZP_SCRATCH_B1")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"^", "xor" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
asmgen.assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla | eor P8ZP_SCRATCH_B1")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"==" -> {
|
||||
TODO("byte == at ${expr.position}")
|
||||
}
|
||||
"!=" -> {
|
||||
TODO("byte != at ${expr.position}")
|
||||
}
|
||||
"<" -> {
|
||||
TODO("byte < at ${expr.position}")
|
||||
}
|
||||
"<=" -> {
|
||||
TODO("byte <= at ${expr.position}")
|
||||
}
|
||||
">" -> {
|
||||
TODO("byte > at ${expr.position}")
|
||||
}
|
||||
">=" -> {
|
||||
TODO("byte >= at ${expr.position}")
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignFloatBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||
when(expr.operator) {
|
||||
"+" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
||||
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC2, true)
|
||||
if(!expr.right.isSimple()) asmgen.popFAC1()
|
||||
asmgen.out(" jsr floats.FADDT")
|
||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||
return true
|
||||
}
|
||||
"-" -> {
|
||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC1, true)
|
||||
if(!expr.left.isSimple()) asmgen.pushFAC1()
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC2, true)
|
||||
if(!expr.left.isSimple()) asmgen.popFAC1()
|
||||
asmgen.out(" jsr floats.FSUBT")
|
||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||
return true
|
||||
}
|
||||
"*" -> {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
||||
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC2, true)
|
||||
if(!expr.right.isSimple()) asmgen.popFAC1()
|
||||
asmgen.out(" jsr floats.FMULTT")
|
||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||
return true
|
||||
}
|
||||
"/" -> {
|
||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC1, true)
|
||||
if(!expr.left.isSimple()) asmgen.pushFAC1()
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC2, true)
|
||||
if(!expr.left.isSimple()) asmgen.popFAC1()
|
||||
asmgen.out(" jsr floats.FDIVT")
|
||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||
return true
|
||||
}
|
||||
"==" -> {
|
||||
setupFloatComparisonFAC1vsVarAY(expr)
|
||||
asmgen.out(" jsr floats.var_fac1_equal_f")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"!=" -> {
|
||||
setupFloatComparisonFAC1vsVarAY(expr)
|
||||
asmgen.out(" jsr floats.var_fac1_notequal_f")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"<" -> {
|
||||
setupFloatComparisonFAC1vsVarAY(expr)
|
||||
asmgen.out(" jsr floats.var_fac1_less_f")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
">" -> {
|
||||
setupFloatComparisonFAC1vsVarAY(expr)
|
||||
asmgen.out(" jsr floats.var_fac1_greater_f")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
"<=" -> {
|
||||
setupFloatComparisonFAC1vsVarAY(expr)
|
||||
asmgen.out(" jsr floats.var_fac1_lesseq_f")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
">=" -> {
|
||||
setupFloatComparisonFAC1vsVarAY(expr)
|
||||
asmgen.out(" jsr floats.var_fac1_greatereq_f")
|
||||
asmgen.assignRegister(RegisterOrPair.A, assign.target)
|
||||
return true
|
||||
}
|
||||
else -> TODO("float expression operator ${expr.operator}")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun setupFloatComparisonFAC1vsVarAY(expr: PtBinaryExpression) {
|
||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
||||
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
||||
asmgen.assignExpressionToVariable(expr.right, "floats.floats_temp_var", DataType.FLOAT)
|
||||
if(!expr.right.isSimple()) asmgen.popFAC1()
|
||||
asmgen.out(" lda #<floats.floats_temp_var | ldy #>floats.floats_temp_var")
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import prog8.codegen.cpu6502.returnsWhatWhere
|
||||
|
||||
internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private val asmgen: AsmGen6502Internal,
|
||||
private val anyExprGen: AnyExprAsmGen,
|
||||
private val allocator: VariableAllocator) {
|
||||
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen, allocator)
|
||||
|
||||
@ -411,7 +412,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
if(expr.type !in IntegerDatatypes)
|
||||
return false
|
||||
return anyExprGen.assignAnyExpressionUsingStack(expr, assign)
|
||||
|
||||
if(expr.operator in setOf("&", "|", "^", "and", "or", "xor"))
|
||||
return optimizedLogicalOrBitwiseExpr(expr, assign.target)
|
||||
@ -428,7 +429,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
if(expr.operator=="%")
|
||||
return optimizedRemainderExpr(expr, assign.target)
|
||||
|
||||
return false
|
||||
return anyExprGen.assignAnyExpressionUsingStack(expr, assign)
|
||||
}
|
||||
|
||||
private fun optimizedRemainderExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
@ -1579,6 +1580,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
if(targetDt==DataType.FLOAT && (target.register==RegisterOrPair.FAC1 || target.register==RegisterOrPair.FAC2)) {
|
||||
if(target.register==RegisterOrPair.FAC2)
|
||||
asmgen.pushFAC1()
|
||||
when(valueDt) {
|
||||
DataType.UBYTE -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.Y, false)
|
||||
@ -1599,7 +1602,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
}
|
||||
if(target.register==RegisterOrPair.FAC2) {
|
||||
asmgen.out(" jsr floats.MOVEF")
|
||||
asmgen.out(" jsr floats.MOVEF")
|
||||
asmgen.popFAC1()
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -2091,8 +2095,9 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
internal fun assignFAC2float(target: AsmAssignTarget) {
|
||||
asmgen.out(" jsr floats.MOVFA") // fac2 -> fac1
|
||||
assignFAC1float(target)
|
||||
asmgen.out(" jsr floats.MOVFA")
|
||||
if(target.register != RegisterOrPair.FAC1)
|
||||
assignFAC1float(target)
|
||||
}
|
||||
|
||||
internal fun assignFAC1float(target: AsmAssignTarget) {
|
||||
@ -2121,7 +2126,9 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
TargetStorageKind.MEMORY -> throw AssemblyError("can't assign float to mem byte")
|
||||
TargetStorageKind.REGISTER -> {
|
||||
if (target.register!! != RegisterOrPair.FAC1)
|
||||
if(target.register==RegisterOrPair.FAC2)
|
||||
asmgen.out(" jsr floats.MOVAF")
|
||||
else if (target.register!! != RegisterOrPair.FAC1)
|
||||
throw AssemblyError("can't assign Fac1 float to another register")
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.AugmentAssignmentOperators
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
|
||||
@ -21,6 +22,9 @@ class BinExprSplitter(private val program: Program, private val options: Compila
|
||||
if(options.compTarget.name == VMTarget.NAME)
|
||||
return noModifications // don't split expressions when targeting the vm codegen, it handles nested expressions well
|
||||
|
||||
if(assignment.value.inferType(program) istype DataType.FLOAT)
|
||||
return noModifications
|
||||
|
||||
val binExpr = assignment.value as? BinaryExpression
|
||||
if (binExpr != null) {
|
||||
|
||||
|
@ -208,7 +208,6 @@ var_fac1_greater_f .proc
|
||||
.pend
|
||||
|
||||
var_fac1_greatereq_f .proc
|
||||
ldx P8ZP_SCRATCH_REG
|
||||
; -- is the float in FAC1 >= the variable AY? Result in A. Clobbers X.
|
||||
jsr FCOMP
|
||||
cmp #0
|
||||
@ -221,6 +220,14 @@ var_fac1_greatereq_f .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
var_fac1_equal_f .proc
|
||||
; -- are the floats numbers in FAC1 and the variable AY *not* identical? Result in A. Clobbers X.
|
||||
jsr FCOMP
|
||||
and #1
|
||||
eor #1
|
||||
rts
|
||||
.pend
|
||||
|
||||
var_fac1_notequal_f .proc
|
||||
; -- are the floats numbers in FAC1 and the variable AY *not* identical? Result in A. Clobbers X.
|
||||
jsr FCOMP
|
||||
@ -381,3 +388,61 @@ set_array_float .proc
|
||||
; -- copies the 5 bytes of the mflt value pointed to by SCRATCH_ZPWORD1,
|
||||
; into the 5 bytes pointed to by A/Y. Clobbers A,Y.
|
||||
.pend
|
||||
|
||||
|
||||
pushFAC1 .proc
|
||||
;-- push floating point in FAC onto the cpu stack
|
||||
; save return address
|
||||
pla
|
||||
sta P8ZP_SCRATCH_W2
|
||||
pla
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
ldx #<floats.floats_temp_var
|
||||
ldy #>floats.floats_temp_var
|
||||
jsr floats.MOVMF
|
||||
lda floats.floats_temp_var
|
||||
pha
|
||||
lda floats.floats_temp_var+1
|
||||
pha
|
||||
lda floats.floats_temp_var+2
|
||||
pha
|
||||
lda floats.floats_temp_var+3
|
||||
pha
|
||||
lda floats.floats_temp_var+4
|
||||
pha
|
||||
; re-push return address
|
||||
lda P8ZP_SCRATCH_W2+1
|
||||
pha
|
||||
lda P8ZP_SCRATCH_W2
|
||||
pha
|
||||
rts
|
||||
.pend
|
||||
|
||||
popFAC1 .proc
|
||||
; -- pop floating point value from cpu stack into FAC1
|
||||
; save return address
|
||||
pla
|
||||
sta P8ZP_SCRATCH_W2
|
||||
pla
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
pla
|
||||
sta floats.floats_temp_var+4
|
||||
pla
|
||||
sta floats.floats_temp_var+3
|
||||
pla
|
||||
sta floats.floats_temp_var+2
|
||||
pla
|
||||
sta floats.floats_temp_var+1
|
||||
pla
|
||||
sta floats.floats_temp_var
|
||||
lda #<floats.floats_temp_var
|
||||
ldy #>floats.floats_temp_var
|
||||
jsr floats.MOVFM
|
||||
; re-push return address
|
||||
lda P8ZP_SCRATCH_W2+1
|
||||
pha
|
||||
lda P8ZP_SCRATCH_W2
|
||||
pha
|
||||
rts
|
||||
.pend
|
||||
|
||||
|
@ -6,10 +6,10 @@ package prog8.buildversion
|
||||
const val MAVEN_GROUP = "prog8"
|
||||
const val MAVEN_NAME = "compiler"
|
||||
const val VERSION = "9.2-SNAPSHOT"
|
||||
const val GIT_REVISION = 3974
|
||||
const val GIT_SHA = "ab8173637a9939352ddb027ecd67f1c42b63b1fc"
|
||||
const val GIT_DATE = "2023-07-16T09:15:28Z"
|
||||
const val GIT_REVISION = 3980
|
||||
const val GIT_SHA = "9f247901d484ca36d047cdcf77f5b905ba772f82"
|
||||
const val GIT_DATE = "2023-07-16T21:45:04Z"
|
||||
const val GIT_BRANCH = "remove_evalstack"
|
||||
const val BUILD_DATE = "2023-07-16T11:04:18Z"
|
||||
const val BUILD_UNIX_TIME = 1689505458888L
|
||||
const val BUILD_DATE = "2023-07-17T23:11:43Z"
|
||||
const val BUILD_UNIX_TIME = 1689635503506L
|
||||
const val DIRTY = 1
|
||||
|
@ -1,8 +1,9 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- (branch): fix float expressions codegen, it relied heavily on the evalstack
|
||||
- (branch): fix float expressions codegen, it relied heavily on the evalstack (mandelbrot example zero division error)
|
||||
- (branch): improve integer expression codegen even more to support even more cases?
|
||||
- (branch): fully remove BinExprSplitter???
|
||||
|
||||
- IR: instructions that do type conversion (SZ etc, CONCAT, SGN) should put the result in a DIFFERENT register.
|
||||
- IR: reduce the number of branch instructions (gradually), replace with CMP(I) + status branch instruction
|
||||
|
@ -9,6 +9,7 @@ main {
|
||||
|
||||
sub start() {
|
||||
txt.print("calculating mandelbrot fractal...\n\n")
|
||||
cbm.SETTIM(0,0,0)
|
||||
|
||||
ubyte pixelx
|
||||
ubyte pixely
|
||||
@ -37,5 +38,10 @@ main {
|
||||
}
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
float duration = (cbm.RDTIM16() as float) / 60
|
||||
txt.print("\nfinished in ")
|
||||
floats.print_f(duration)
|
||||
txt.print(" seconds!\n")
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,47 @@
|
||||
%import textio
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
|
||||
main
|
||||
{
|
||||
sub start()
|
||||
{
|
||||
uword uw = 54321
|
||||
ubyte ub = 123
|
||||
word sw = -12345
|
||||
byte sb = -123
|
||||
main {
|
||||
const uword width = 60
|
||||
const uword height = 50
|
||||
const ubyte max_iter = 16
|
||||
|
||||
txt.print_uw(~ub as uword) ;132
|
||||
txt.nl()
|
||||
txt.print_ub(~uw as ubyte) ;206
|
||||
txt.nl()
|
||||
txt.print_uw(~sb as uword) ;122
|
||||
txt.nl()
|
||||
txt.print_ub(~sw as ubyte) ;56
|
||||
txt.nl()
|
||||
txt.print_w(-sb as word) ;123
|
||||
txt.nl()
|
||||
txt.print_b(-sw as byte) ;57
|
||||
txt.nl()
|
||||
sub start() {
|
||||
txt.print("calculating mandelbrot fractal...\n\n")
|
||||
cbm.SETTIM(0,0,0)
|
||||
|
||||
ubyte pixelx
|
||||
ubyte pixely
|
||||
|
||||
for pixely in 0 to height-1 {
|
||||
float yy = (pixely as float)/0.40/height - 1.3
|
||||
|
||||
for pixelx in 0 to width-1 {
|
||||
float xx = (pixelx as float)/0.32/width - 2.2
|
||||
|
||||
float xsquared = 0.0
|
||||
float ysquared = 0.0
|
||||
float x = 0.0
|
||||
float y = 0.0
|
||||
ubyte iter = 0
|
||||
|
||||
while iter<max_iter and xsquared+ysquared<4.0 {
|
||||
y = x*y*2.0 + yy
|
||||
x = xsquared - ysquared + xx
|
||||
xsquared = x*x
|
||||
ysquared = y*y
|
||||
iter++
|
||||
}
|
||||
txt.color2(1, max_iter-iter)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
float duration = (cbm.RDTIM16() as float) / 60
|
||||
txt.print("\nfinished in ")
|
||||
floats.print_f(duration)
|
||||
txt.print(" seconds!\n")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user