PutBitBranch, PutBitBranch_m740, PutBlockTransfer and PutLDM_m740 emitted
the opcode (and the zero page byte) before reading the remaining operands.
Since '*' is evaluated while the operand is read, it pointed one or two
bytes into the instruction instead of at its start:
bbr0 $12,* ; was 0F 12 FF, now 0F 12 FD (loops on itself)
tii *,$2000,1 ; source address was off by one
ldm $12,#<* ; immediate was off by two
The usual "wait for a port bit" idiom `bbr0 port,*` therefore jumped into
the middle of the next instruction. Branches to labels were not affected.
Now all operands are read first and emitted afterwards, as for every other
instruction.
In addition, the m740 accumulator form `bbs/bbc i,a,rel` is a 2 byte
instruction, but its offset was computed relative to the end of a 3 byte
one, so it was off by one even with labels. da65 had the matching error
(PC+3 instead of PC+2) in OH_AccumulatorBitBranch, which is why the
round trip test did not catch it. Both are fixed.
Reference binaries that encoded the old offsets are regenerated: the only
differences are the 16 bit branch offsets in each file. The 65C02 da65
test used `bbrN $12,*+2` meaning "next instruction"; with correct '*'
that is `*+3`.
New test: test/asm/listing/313-bitbranch-star.s, with hand-computed bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Per CPU, a test binary is produced (using the assembler), which should contain all possible instructions. That file is then disassembled, and assembled again, and finally the resulting binary compared with the binary produced in the first step. Given that we assume the assembler works (this is tested in other/previous tests), this proves that the disassembler works, and can produce output that the assembler will understand - and produce an identical binary from.