This is niche, but I think we can provide an interesting, and dare I say innovative, improvement with relatively little effort.
Rationale. Sometimes we write timed code, for example because we're syncing to the PPU. The common practice is to write something like this:
halt
ld a, [de] ; 2
ld [hli], a ; 2
inc e ; 1
; 5 is less than 16, so we're good.
...this is manual and error-prone, so I'd like a way to automate (parts of) this. I think we could have a __CYCLES__ variable, which can be modified like any other, but that also gets automatically increased by however many cycles each instruction takes.
halt
def __CYCLES__ = 0
ld a, [de]
ld [hli], a
inc e
assert __CYCLES__ <= 16, "Overflowed safe VRAM access time!"
Edge cases.
db is sometimes used for code. I think this shouldn't be taken into account, as the user can adjust __CYCLES__ themselves as necessary. For example:
MACRO code_db
db \#
def __CYCLES__ += _NARG
ENDM
- Control flow instructions should not be treated specially (no attempt made to do any kind of control flow analysis).
- Conditional instructions should be handled in a way as useful as we can make it while keeping it useful. I think treating them as untaken always achieves that goal, as either all branches take the same number of cycles (e.g.
jr nc, .noCarry :: inc h :: .noCarry) or a single measure isn't going to be sufficient anyway.
- Opening a section should automatically
def __CYCLES__ = 0 for convenience. We don't need to provide an opt-out, since I expect that would be rare, and it can be done manually with
def cycles equ __CYCLES__
SECTION "...", ROM0
def __CYCLES__ = cycles
This is niche, but I think we can provide an interesting, and dare I say innovative, improvement with relatively little effort.
Rationale. Sometimes we write timed code, for example because we're syncing to the PPU. The common practice is to write something like this:
...this is manual and error-prone, so I'd like a way to automate (parts of) this. I think we could have a
__CYCLES__variable, which can be modified like any other, but that also gets automatically increased by however many cycles each instruction takes.Edge cases.
dbis sometimes used for code. I think this shouldn't be taken into account, as the user can adjust__CYCLES__themselves as necessary. For example:jr nc, .noCarry :: inc h :: .noCarry) or a single measure isn't going to be sufficient anyway.def __CYCLES__ = 0for convenience. We don't need to provide an opt-out, since I expect that would be rare, and it can be done manually with