The label table is kept in order, and halved instead of walked
labFind walked the index from the front, so every use of every label cost a scan of every label defined so far, each with a string compare. The cost grew with the program being built, which is what made it hurt: assembling CosmOS on the machine took 1,833,691,267 cycles against the assembler assembling itself at 57,257,133 - three times the source for thirty two times the time. Sorted and halved, the same build is 886,498,996. THE WALK WAS 52 PER CENT OF THE WHOLE ASSEMBLY, which settles a suspicion this project has carried unverified for weeks and puts a number on it. Eleven comparisons against two thousand entries where a walk averaged six hundred and seventy. The search hands back where a name WOULD go, which is what adding one needs and what a walk could never have offered, so labAdd gets its insertion point for nothing. sameText was already an ordering and did not have to change: Q is the difference at the first character that differed, and the Carry Flag from that same subtraction survives the return because nothing puts the Status register back. A name that runs out while the other carries on borrows against the other's character, which sorts the shorter first. Small programs pay about a tenth more - 57.3M to 63.5M for the assembler on itself - because adding a label now moves the tail of the index up and a short table was never expensive to walk. That is the right way round for a trade to fall. numHalve and numBack are new: a rotate right on a CIRCULAR sixteen bit register brings bit nought back in at the top, so halving means taking that bit off again, and the low half has to go down first because the mask wants B. WHICH END THE TABLE IS SORTED FROM DOES NOT MATTER. labAdd takes its insertion point from labFind, so the comparison that decides the order is the same one that searches it - turn it round and the table is built backwards and read backwards and no output changes. Tests/break.sh says so, correctly, by not noticing. Verified by CosmOS builds CosmOS and second generation staying byte identical. An indexing bug cannot hide behind a fixed point. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
563bc20a75
commit
e20c9bac1f
@@ -112,6 +112,45 @@ numCompare:
|
||||
numCompareDone:
|
||||
RET
|
||||
|
||||
; Takes one off the two byte number at DP0. The mirror of numStep, and wanted for the same
|
||||
; reason: walking an index backwards is what moving a run of entries up needs.
|
||||
numBack:
|
||||
INCD.0
|
||||
LDA.0
|
||||
BNA numBackLow ; The low half has something to take, so the high half is safe.
|
||||
DECD.0
|
||||
LDA.0
|
||||
DECA
|
||||
STA.0
|
||||
INCD.0
|
||||
LDA.0
|
||||
numBackLow:
|
||||
DECA
|
||||
STA.0
|
||||
RET
|
||||
|
||||
; The two byte number at DP0 becomes half of itself.
|
||||
;
|
||||
; A and B are a CIRCULAR sixteen bit register, so a rotate right brings bit nought back in at
|
||||
; the top rather than dropping it - which is a halving only once that bit is taken off again.
|
||||
; The numbers this is asked about are index positions, well under thirty two thousand, so the
|
||||
; top bit was nought before the rotate and clearing it afterwards loses nothing.
|
||||
numHalve:
|
||||
LDA.0
|
||||
INCD.0
|
||||
LDB.0
|
||||
SHR
|
||||
|
||||
; The low half goes down FIRST, because taking the wrapped bit off the high half wants B
|
||||
; for the mask and there is nowhere else to keep it.
|
||||
STB.0
|
||||
INIB 0x7F
|
||||
AND
|
||||
MVQA
|
||||
DECD.0
|
||||
STA.0
|
||||
RET
|
||||
|
||||
; Q is zero if the strings at DP0 and DP1 are the same, both ending in a zero byte.
|
||||
;
|
||||
; Down here rather than with the label table, where it started, because four separate
|
||||
|
||||
Reference in New Issue
Block a user