mirror of
https://github.com/irmen/prog8.git
synced 2025-07-24 05:24:17 +00:00
Compare commits
8 Commits
structs-wi
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
866313209b | ||
|
e2901cca1b | ||
|
dd7adde387 | ||
|
2f90c53ad0 | ||
|
720988ae72 | ||
|
ea5deeefbd | ||
|
054c98da7c | ||
|
a4a1b563aa |
@@ -328,10 +328,9 @@ internal class ProgramAndVarsGen(
|
||||
if (initializers.isNotEmpty()) {
|
||||
asmgen.out("prog8_init_vars\t.block")
|
||||
initializers.forEach { assign ->
|
||||
if((assign.value as? PtNumber)?.number != 0.0 || allocator.isZpVar(assign.target.identifier!!.name))
|
||||
val constvalue = assign.value as? PtNumber
|
||||
if(constvalue==null || constvalue.number!=0.0 || allocator.isZpVar(assign.target.identifier!!.name))
|
||||
asmgen.translate(assign)
|
||||
else
|
||||
throw AssemblyError("non-zp variable should not be initialized to zero; it will be zeroed as part of BSS clear")
|
||||
// the other variables that should be set to zero are done so as part of the BSS section clear.
|
||||
}
|
||||
asmgen.out(" rts\n .bend")
|
||||
|
@@ -75,7 +75,7 @@ class IRCodeGen(
|
||||
initsToRemove += block to initialization
|
||||
}
|
||||
is PtNumber -> {
|
||||
require(initValue.number!=0.0) { "variable should not be initialized with 0, it will already be zeroed as part of BSS clear, initializer=$initialization" }
|
||||
require(initValue.number!=0.0 || variable.zpwish!=ZeropageWish.NOT_IN_ZEROPAGE) {"non-zp variable should not be initialized with 0, it will already be zeroed as part of BSS clear, initializer=$initialization" }
|
||||
variable.setOnetimeInitNumeric(initValue.number)
|
||||
initsToRemove += block to initialization
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ class StatementOptimizer(private val program: Program,
|
||||
val functionName = functionCallStatement.target.nameInSource[0]
|
||||
if (functionName in functions.purefunctionNames) {
|
||||
if("ignore_unused" !in parent.definingBlock.options())
|
||||
errors.info("statement has no effect (function return value is discarded)", functionCallStatement.position)
|
||||
errors.warn("statement has no effect (function return value is discarded)", functionCallStatement.position)
|
||||
return listOf(IAstModification.Remove(functionCallStatement, parent as IStatementContainer))
|
||||
}
|
||||
}
|
||||
|
@@ -376,7 +376,7 @@ hline_filled_right .byte 0, %10000000, %11000000, %11100000, %11110000, %1111
|
||||
_ormask .byte 128, 64, 32, 16, 8, 4, 2, 1
|
||||
|
||||
; note: this can be even faster if we also have a 320 word x-lookup table, but hey, that's a lot of memory.
|
||||
; see http://codebase64.org/doku.php?id=base:various_techniques_to_calculate_adresses_fast_common_screen_formats_for_pixel_graphics
|
||||
; see https://codebase64.net/doku.php?id=base:various_techniques_to_calculate_adresses_fast_common_screen_formats_for_pixel_graphics
|
||||
; the y lookup tables encodes this formula: BITMAP_ADDRESS + 320*(py>>3) + (py & 7) (y from 0..199)
|
||||
; We use the 64tass syntax for range expressions to calculate this table on assembly time.
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
;
|
||||
; some more interesting routines can be found here:
|
||||
; http://6502org.wikidot.com/software-math
|
||||
; http://codebase64.org/doku.php?id=base:6502_6510_maths
|
||||
; https://codebase64.net/doku.php?id=base:6502_6510_maths
|
||||
; https://github.com/TobyLobster/multiply_test
|
||||
; https://github.com/TobyLobster/sqrt_test
|
||||
|
||||
@@ -353,7 +353,7 @@ _divisor .word ?
|
||||
randword .proc
|
||||
; -- 16 bit pseudo random number generator into AY
|
||||
; default seed = $00c2 $1137. NOTE: uses self-modifying code so won't work in ROM (use randword_rom instead)
|
||||
; routine from https://codebase64.org/doku.php?id=base:x_abc_random_number_generator_8_16_bit
|
||||
; routine from https://codebase64.net/doku.php?id=6502_6510_maths:x_abc_random_number_generator_8_16_bit
|
||||
inc x1
|
||||
clc
|
||||
x1=*+1
|
||||
@@ -377,7 +377,7 @@ b1=*+1
|
||||
randword_rom .proc
|
||||
; -- 16 bit pseudo random number generator into AY. Can run from ROM.
|
||||
; NOTE: you have to set the initial seed using randseed_rom! (a good default seed = $00c2 $1137)
|
||||
; routine from https://codebase64.org/doku.php?id=base:x_abc_random_number_generator_8_16_bit
|
||||
; routine from https://codebase64.net/doku.php?id=6502_6510_maths:x_abc_random_number_generator_8_16_bit
|
||||
inc _x1
|
||||
clc
|
||||
lda _x1
|
||||
|
@@ -380,7 +380,7 @@ _quadrant_region_to_direction:
|
||||
asmsub atan2(ubyte x1 @R0, ubyte y1 @R1, ubyte x2 @R2, ubyte y2 @R3) -> ubyte @A {
|
||||
;; Calculate the angle, in a 256-degree circle, between two points into A.
|
||||
;; The points (x1, y1) and (x2, y2) have to use *unsigned coordinates only* from the positive quadrant in the carthesian plane!
|
||||
;; https://www.codebase64.org/doku.php?id=base:8bit_atan2_8-bit_angle
|
||||
;; http://codebase64.net/doku.php?id=base:8bit_atan2_8-bit_angle
|
||||
;; This uses 2 large lookup tables so uses a lot of memory but is super fast.
|
||||
|
||||
%asm {{
|
||||
|
@@ -138,8 +138,8 @@ diskio {
|
||||
; you can call this multiple times to append more data
|
||||
repeat num_bytes {
|
||||
%ir {{
|
||||
loadm.w r0,diskio.f_write.bufferpointer
|
||||
loadi.b r99100,r0
|
||||
loadm.w r99000,diskio.f_write.bufferpointer
|
||||
loadi.b r99100,r99000
|
||||
syscall 55 (r99100.b): r99100.b
|
||||
storem.b r99100,$ff02
|
||||
}}
|
||||
@@ -216,12 +216,12 @@ diskio {
|
||||
}
|
||||
|
||||
; like save() but omits the 2 byte prg header.
|
||||
sub save_raw(uword filenameptr, uword startaddress, uword savesize) -> bool {
|
||||
sub save_raw(uword filenameptr, uword start_address, uword savesize) -> bool {
|
||||
%ir {{
|
||||
load.b r99100,1
|
||||
loadm.w r99000,diskio.save.filenameptr
|
||||
loadm.w r99001,diskio.save.start_address
|
||||
loadm.w r99002,diskio.save.savesize
|
||||
loadm.w r99000,diskio.save_raw.filenameptr
|
||||
loadm.w r99001,diskio.save_raw.start_address
|
||||
loadm.w r99002,diskio.save_raw.savesize
|
||||
syscall 42 (r99100.b, r99000.w, r99001.w, r99002.w): r99100.b
|
||||
returnr.b r99100
|
||||
}}
|
||||
|
@@ -468,7 +468,7 @@ private fun processAst(program: Program, errors: IErrorReporter, compilerOptions
|
||||
errors.report()
|
||||
program.constantFold(errors, compilerOptions)
|
||||
errors.report()
|
||||
program.reorderStatements(errors)
|
||||
program.reorderStatements(compilerOptions, errors)
|
||||
errors.report()
|
||||
program.desugaring(errors, compilerOptions)
|
||||
errors.report()
|
||||
|
@@ -1470,6 +1470,17 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
override fun visit(functionCallStatement: FunctionCallStatement) {
|
||||
|
||||
if(functionCallStatement.target.nameInSource.size==1) {
|
||||
val functionName = functionCallStatement.target.nameInSource[0]
|
||||
if (functionName in program.builtinFunctions.purefunctionNames) {
|
||||
if("ignore_unused" !in functionCallStatement.parent.definingBlock.options()) {
|
||||
errors.warn("statement has no effect (function return value is discarded)", functionCallStatement.position)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// most function calls, even to builtin functions, are still regular FunctionCall nodes here.
|
||||
// they get converted to the more specialized node type in BeforeAsmTypecastCleaner
|
||||
val targetStatement = functionCallStatement.target.checkFunctionOrLabelExists(program, functionCallStatement, errors)
|
||||
|
@@ -20,8 +20,8 @@ internal fun Program.checkValid(errors: IErrorReporter, compilerOptions: Compila
|
||||
checker.visit(this)
|
||||
}
|
||||
|
||||
internal fun Program.reorderStatements(errors: IErrorReporter) {
|
||||
val reorder = StatementReorderer(this, errors)
|
||||
internal fun Program.reorderStatements(options: CompilationOptions, errors: IErrorReporter) {
|
||||
val reorder = StatementReorderer(this, options, errors)
|
||||
reorder.visit(this)
|
||||
if(errors.noErrors()) {
|
||||
reorder.applyModifications()
|
||||
|
@@ -165,8 +165,11 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
}
|
||||
}
|
||||
|
||||
if(srcAssign.origin == AssignmentOrigin.VARINIT && srcAssign.parent is Block && srcAssign.value.constValue(program)?.number==0.0)
|
||||
throw FatalAstException("should not have a redundant block-level variable=0 assignment; it will be zeroed as part of BSS clear")
|
||||
if(srcAssign.origin == AssignmentOrigin.VARINIT && srcAssign.parent is Block && srcAssign.value.constValue(program)?.number==0.0) {
|
||||
val zeropages = srcAssign.target.targetIdentifiers().mapNotNull { it.targetVarDecl()?.zeropage }
|
||||
if(zeropages.any {it==ZeropageWish.NOT_IN_ZEROPAGE})
|
||||
throw FatalAstException("should not have a redundant block-level variable=0 assignment for a non-ZP variable; it will be zeroed as part of BSS clear")
|
||||
}
|
||||
|
||||
val assign = PtAssignment(srcAssign.position, srcAssign.origin==AssignmentOrigin.VARINIT)
|
||||
val multi = srcAssign.target.multi
|
||||
|
@@ -133,7 +133,7 @@ private fun integrateDefers(subdefers: Map<PtSub, List<PtDefer>>, program: PtPro
|
||||
is PtNumber,
|
||||
is PtRange,
|
||||
is PtString -> true
|
||||
// note that unlike most other times, PtIdentifier IS "complex" this time (it's a variable that might change)
|
||||
is PtIdentifier -> true // actually PtIdentifier IS "complex" this time (it's a variable that might change) but it's kinda annoying to give a warning message for this very common case
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
@@ -5,13 +5,11 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.AssociativeOperators
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.*
|
||||
|
||||
internal class StatementReorderer(
|
||||
val program: Program,
|
||||
val options: CompilationOptions,
|
||||
val errors: IErrorReporter
|
||||
) : AstWalker() {
|
||||
// Reorders the statements in a way the compiler needs.
|
||||
@@ -114,11 +112,18 @@ internal class StatementReorderer(
|
||||
}
|
||||
|
||||
private fun canSkipInitializationWith0(decl: VarDecl): Boolean {
|
||||
// if the variable is declared in a block, we can omit the init with 0 because
|
||||
if(decl.parent is Block) {
|
||||
// if the variable is declared in a block and is NOT in ZEROPAGE, we can omit the init with 0 because
|
||||
// the variable will be initialized to zero when the BSS section is cleared as a whole.
|
||||
if(decl.parent is Block)
|
||||
if (decl.zeropage == ZeropageWish.NOT_IN_ZEROPAGE)
|
||||
return true
|
||||
|
||||
// block level zp var that is not in zeropage, doesn't have to be cleared (will be done as part of bss clear at startup)
|
||||
// note: subroutine level var HAS to be cleared because it needs to be zero at every subroutine call!
|
||||
if (decl.zeropage == ZeropageWish.DONTCARE && options.zeropage == ZeropageType.DONTUSE)
|
||||
return true
|
||||
}
|
||||
|
||||
// if there is an assignment to the variable below it (regular assign, or For loop),
|
||||
// and there is nothing important in between, we can skip the initialization.
|
||||
val statements = (decl.parent as? IStatementContainer)?.statements ?: return false
|
||||
|
@@ -5,6 +5,7 @@ import io.kotest.engine.spec.tempdir
|
||||
import io.kotest.inspectors.shouldForAll
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import prog8.ast.expressions.NumericLiteral
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
@@ -13,6 +14,7 @@ import prog8.code.core.BuiltinFunctions
|
||||
import prog8.code.core.RegisterOrPair
|
||||
import prog8.code.core.isNumeric
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
class TestBuiltinFunctions: FunSpec({
|
||||
@@ -103,5 +105,31 @@ main {
|
||||
|
||||
compileText(Cx16Target(), true, src, outputDir, writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
|
||||
test("warning for return value discarding of pure functions") {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
word @shared ww = 2222
|
||||
|
||||
abs(ww)
|
||||
sgn(ww)
|
||||
sqrt(ww)
|
||||
min(ww, 0)
|
||||
max(ww, 0)
|
||||
clamp(ww, 0, 319)
|
||||
}
|
||||
}"""
|
||||
|
||||
val errors = ErrorReporterForTests(keepMessagesAfterReporting = true)
|
||||
compileText(Cx16Target(), true, src, outputDir, errors=errors, writeAssembly = false) shouldNotBe null
|
||||
errors.warnings.size shouldBe 6
|
||||
errors.warnings[0] shouldContain "statement has no effect"
|
||||
errors.warnings[1] shouldContain "statement has no effect"
|
||||
errors.warnings[2] shouldContain "statement has no effect"
|
||||
errors.warnings[3] shouldContain "statement has no effect"
|
||||
errors.warnings[4] shouldContain "statement has no effect"
|
||||
errors.warnings[5] shouldContain "statement has no effect"
|
||||
}
|
||||
})
|
||||
|
||||
|
@@ -10,7 +10,10 @@ import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.AssignmentOrigin
|
||||
import prog8.ast.statements.ForLoop
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.code.ast.PtAssignment
|
||||
import prog8.code.ast.PtNumber
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8tests.helpers.ErrorReporterForTests
|
||||
import prog8tests.helpers.compileText
|
||||
|
||||
@@ -106,6 +109,7 @@ class TestVariables: FunSpec({
|
||||
|
||||
test("global var init with array lookup should sometimes be const") {
|
||||
val src="""
|
||||
%zeropage dontuse
|
||||
main {
|
||||
|
||||
bool[] barray = [true, false, true, false]
|
||||
@@ -220,4 +224,85 @@ main {
|
||||
(st[5] as Assignment).target.identifier?.nameInSource shouldBe listOf("v1")
|
||||
(st[6] as Assignment).target.identifier?.nameInSource shouldBe listOf("v0")
|
||||
}
|
||||
|
||||
test("nondirty zp variables should be explicitly initialized to 0") {
|
||||
val src="""
|
||||
main {
|
||||
ubyte @shared @requirezp zpvar
|
||||
ubyte @shared @requirezp @dirty dirtyzpvar
|
||||
|
||||
sub start() {
|
||||
ubyte @shared @requirezp zpvar2
|
||||
ubyte @shared @requirezp @dirty dirtyzpvar2
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = true)!!.codegenAst
|
||||
|
||||
val main = result!!.allBlocks().first { it.name=="p8b_main" }
|
||||
main.children.size shouldBe 4
|
||||
val zeroassignlobal = main.children.single { it is PtAssignment } as PtAssignment
|
||||
(zeroassignlobal.value as PtNumber).number shouldBe 0.0
|
||||
zeroassignlobal.target.identifier!!.name shouldBe "p8b_main.p8v_zpvar"
|
||||
|
||||
val st = result.entrypoint()!!.children
|
||||
st.size shouldBe 4
|
||||
val zeroassign = st.single { it is PtAssignment } as PtAssignment
|
||||
(zeroassign.value as PtNumber).number shouldBe 0.0
|
||||
zeroassign.target.identifier!!.name shouldBe "p8b_main.p8s_start.p8v_zpvar2"
|
||||
}
|
||||
|
||||
test("nondirty non zp variables in block scope should not be explicitly initialized to 0 (bss clear takes care of it)") {
|
||||
val src="""
|
||||
%zeropage dontuse
|
||||
|
||||
main {
|
||||
ubyte @shared v1
|
||||
ubyte @shared @dirty dv1
|
||||
sub start() {
|
||||
ubyte @shared v2
|
||||
ubyte @shared @dirty dv2
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = true)!!.codegenAst
|
||||
|
||||
// block level should not be intialized to 0 (will be done by BSS clear)
|
||||
val main = result!!.allBlocks().first { it.name=="p8b_main" }
|
||||
main.children.size shouldBe 3
|
||||
main.children.any { it is PtAssignment } shouldBe false
|
||||
|
||||
// subroutine should be initialized to 0 because that needs to be done on every call to the subroutine
|
||||
val st = result.entrypoint()!!.children
|
||||
st.size shouldBe 4
|
||||
val zeroassign = st.single { it is PtAssignment } as PtAssignment
|
||||
(zeroassign.value as PtNumber).number shouldBe 0.0
|
||||
zeroassign.target.identifier!!.name shouldBe "p8b_main.p8s_start.p8v_v2"
|
||||
}
|
||||
|
||||
test("nondirty explicit non zp variables in block scope should not be explicitly initialized to 0 (bss clear takes care of it)") {
|
||||
val src="""
|
||||
main {
|
||||
ubyte @shared @nozp v1
|
||||
ubyte @shared @dirty @nozp dv1
|
||||
sub start() {
|
||||
ubyte @shared @nozp v2
|
||||
ubyte @shared @dirty @nozp dv2
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = true)!!.codegenAst
|
||||
|
||||
// block level should not be intialized to 0 (will be done by BSS clear)
|
||||
val main = result!!.allBlocks().first { it.name=="p8b_main" }
|
||||
main.children.size shouldBe 3
|
||||
main.children.any { it is PtAssignment } shouldBe false
|
||||
|
||||
// subroutine should be initialized to 0 because that needs to be done on every call to the subroutine
|
||||
val st = result.entrypoint()!!.children
|
||||
st.size shouldBe 4
|
||||
val zeroassign = st.single { it is PtAssignment } as PtAssignment
|
||||
(zeroassign.value as PtNumber).number shouldBe 0.0
|
||||
zeroassign.target.identifier!!.name shouldBe "p8b_main.p8s_start.p8v_v2"
|
||||
}
|
||||
})
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.12" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@@ -27,7 +27,7 @@ of these library modules automatically as required.
|
||||
|
||||
.. note::
|
||||
Several algorithms and math routines in Prog8's assembly library files are adapted from
|
||||
code publicly available on https://www.codebase64.org/
|
||||
code publicly available on https://www.codebase64.net/
|
||||
|
||||
|
||||
.. _builtinfunctions:
|
||||
|
@@ -65,6 +65,11 @@ Various things:
|
||||
and it does it at run time. In this demo a jump table is not only created in the library,
|
||||
but also in the main program and copied into the library for its use.
|
||||
|
||||
`Additional custom compilation targets (such as VIC-20) <https://github.com/gillham/prog8targets>`_
|
||||
Various custom targets for Prog8 that are not (yet?) part of the Prog8 examples themselves.
|
||||
These additional compilation targets may be in varying state of completeness.
|
||||
Perhaps most recognisable at the time of adding this link, are the various VIC-20 targets.
|
||||
|
||||
|
||||
.. image:: _static/curious.png
|
||||
:align: center
|
||||
|
@@ -1,6 +1,10 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
Since fixing the missing zp-var initialization, programs grew in size again (assem)
|
||||
Are there any redundant block-level variable initializations to 0 that we can remove in peephole optimization for example?
|
||||
|
||||
|
||||
STRUCTS: are being developed in their own separate branch for now, called "structs".
|
||||
Idea is to make it feature complete in the IR/Virtual target, then merge it to master?, and then start building the 6502 code generation for it.
|
||||
|
||||
|
@@ -1,27 +1,84 @@
|
||||
%option no_sysinit
|
||||
%zeropage kernalsafe
|
||||
%import textio
|
||||
%zpallowed 224,255
|
||||
|
||||
main {
|
||||
uword @shared @requirezp zpvar1
|
||||
uword @shared @requirezp zpvar2
|
||||
uword @shared @requirezp zpvar3
|
||||
uword @shared @requirezp zpvar4
|
||||
uword @shared @requirezp zpvar5
|
||||
uword @shared @requirezp @dirty dzpvar1
|
||||
uword @shared @requirezp @dirty dzpvar2
|
||||
uword @shared @requirezp @dirty dzpvar3
|
||||
uword @shared @requirezp @dirty dzpvar4
|
||||
uword @shared @requirezp @dirty dzpvar5
|
||||
uword @shared @nozp var1
|
||||
uword @shared @nozp var2
|
||||
uword @shared @nozp var3
|
||||
uword @shared @nozp var4
|
||||
uword @shared @nozp var5
|
||||
uword @shared @nozp @dirty dvar1
|
||||
uword @shared @nozp @dirty dvar2
|
||||
uword @shared @nozp @dirty dvar3
|
||||
uword @shared @nozp @dirty dvar4
|
||||
uword @shared @nozp @dirty dvar5
|
||||
|
||||
sub start() {
|
||||
uword uw = 9999
|
||||
word sw = -2222
|
||||
ubyte ub = 42
|
||||
byte sb = -99
|
||||
bool bb = true
|
||||
txt.print("address start of zpvars: ")
|
||||
txt.print_uw(&zpvar1)
|
||||
txt.nl()
|
||||
txt.print("address start of normal vars: ")
|
||||
txt.print_uw(&var1)
|
||||
txt.nl()
|
||||
|
||||
cx16.r0 = uw
|
||||
cx16.r0s = sw
|
||||
cx16.r0L = ub
|
||||
cx16.r0H = ub
|
||||
cx16.r0sL = sb
|
||||
cx16.r0sH = sb
|
||||
cx16.r0bL = bb
|
||||
cx16.r0bH = bb
|
||||
txt.print("non-dirty zp should all be 0: ")
|
||||
txt.print_uw(zpvar1)
|
||||
txt.spc()
|
||||
txt.print_uw(zpvar2)
|
||||
txt.spc()
|
||||
txt.print_uw(zpvar3)
|
||||
txt.spc()
|
||||
txt.print_uw(zpvar4)
|
||||
txt.spc()
|
||||
txt.print_uw(zpvar5)
|
||||
txt.nl()
|
||||
txt.print("non-dirty should all be 0: ")
|
||||
txt.print_uw(var1)
|
||||
txt.spc()
|
||||
txt.print_uw(var2)
|
||||
txt.spc()
|
||||
txt.print_uw(var3)
|
||||
txt.spc()
|
||||
txt.print_uw(var4)
|
||||
txt.spc()
|
||||
txt.print_uw(var5)
|
||||
txt.nl()
|
||||
|
||||
uw = cx16.r0
|
||||
sw = cx16.r0s
|
||||
ub = cx16.r0L
|
||||
ub = cx16.r0H
|
||||
sb = cx16.r0sL
|
||||
sb = cx16.r0sH
|
||||
bb = cx16.r0bL
|
||||
bb = cx16.r0bH
|
||||
txt.print("dirty zp may be random: ")
|
||||
txt.print_uw(dzpvar1)
|
||||
txt.spc()
|
||||
txt.print_uw(dzpvar2)
|
||||
txt.spc()
|
||||
txt.print_uw(dzpvar3)
|
||||
txt.spc()
|
||||
txt.print_uw(dzpvar4)
|
||||
txt.spc()
|
||||
txt.print_uw(dzpvar5)
|
||||
txt.nl()
|
||||
txt.print("dirty may be random: ")
|
||||
txt.print_uw(dvar1)
|
||||
txt.spc()
|
||||
txt.print_uw(dvar2)
|
||||
txt.spc()
|
||||
txt.print_uw(dvar3)
|
||||
txt.spc()
|
||||
txt.print_uw(dvar4)
|
||||
txt.spc()
|
||||
txt.print_uw(dvar5)
|
||||
txt.nl()
|
||||
|
||||
repeat {}
|
||||
}
|
||||
}
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
@@ -11,8 +11,10 @@ Intermediate Representation instructions for the IR Virtual machine.
|
||||
|
||||
Specs of the virtual machine this will run on:
|
||||
Program to execute is not stored in the system memory, it's just a separate list of instructions.
|
||||
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
||||
65536 virtual floating point registers (64 bits double precision) fr0-fr65535
|
||||
100K virtual registers, 16 bits wide, can also be used as 8 bits. r0-r99999
|
||||
reserved 99000 - 99099 : WORD registers for syscall arguments and response value(s)
|
||||
reserved 99100 - 99199 : BYTE registers for syscall arguments and response value(s)
|
||||
100K virtual floating point registers (64 bits double precision) fr0-fr99999
|
||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||
Value stack, max 128 entries of 1 byte each.
|
||||
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC,
|
||||
|
@@ -200,7 +200,7 @@ class StStaticVariable(name: String,
|
||||
// Certain codegens might want to put them back into the variable directly.
|
||||
// For strings and arrays this doesn't occur - these are always already specced at creation time.
|
||||
|
||||
require(number!=0.0) { "variable should not be initialized with 0, it will already be zeroed as part of BSS clear" }
|
||||
require(number!=0.0 || zpwish!=ZeropageWish.NOT_IN_ZEROPAGE) { "non-zp variable should not be initialized with 0, it will already be zeroed as part of BSS clear" }
|
||||
initializationNumericValue = number
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user