Arguably every hardware register should be declared that way as a symbol
Not sure if Borland or MS shipped big fat symbol tables for all hardware registers of an IBM PC though?
_clear_screen:
move.w #28672,3932160
move.w #1,3932164
move.l #3932162,a0
move.w #-13570,d1
move.w #1279,d0
.L2:
move.w d1,(a0)
dbra d0,.L2
rtsSpecifically, I heard that the 68k backend keeps getting worse, whilst the front-end keeps getting better. So choosing a GCC version is a case of examining the tradeoffs between getting better AST-level optimisations from a newer version, or more optimised assembly language output from an earlier version.
I imagine GCC 6.5 probably has a backend that makes better use of the 68k chip than the GCC 11.4 that ngdevkit uses (such as knowing when to use dbra) but is probably worse in other ways due to an older and less capable frontend.
When playing King of Fighters, the time counter would go down to 0 and then wrap around to 99, effectively preventing the round from ending.
Eventually I tracked it down to the behavior of SBCD (Subtract Binary Coded Decimal): Internally, the chip actually does update the overflow flag reliably (it's marked as undefined in the docs). SNK was checking the V flag and ending the round when it got set.
https://github.com/kstenerud/Musashi/blob/master/m68k_in.c#L...
SBCD was an old throwback instruction that was hardly used anymore, and the register variant took 6 cycles to complete (vs 4 for binary subtraction).
HOWEVER... For displaying the timer counter on-screen, they saved a ton of cycles with this scheme because extracting the digits from a BCD value is a simple shift by 4 bits (6 cycles) rather than a VERY expensive divide (140 cycles).
A software implementation with masks and shifts will beat traditional CISC dividers.
This is actually required rather than an optimisation for any C compiler, from early on, as C semantically allows constant expressions rather than just constants to be used for statically allocated sizes, etc. While the 'optimisation' is not guaranteed you'll see even on -O0 the constant was evaluated at compile-time, as it's harder to not fold constant expressions sometimes than it is to just always fold them for the already required constant expression features.
.L2:
move.w d1,(a0)
move.w d1,(a0)
move.w d1,(a0)
move.w d1,(a0)
dbra d0,.L2
rts;-)
dmitrygr•4mo ago