I spent a lot of time in the 80s going through 6502 ROMs for home computers. I can honestly tell you what the BIT instruction is used for most of the time in practice.
Mostly it's not used for any calculation of interest. It's used as a filler instruction to allow multiple entry points to a routine, each with different common parameter values. I don't think I ever saw it used for the intended purpose. (Maybe once or twice.)
So for example if you had a routine which prints an ASCII character, you might commonly want to print space, or carriage return or things like '?' on the Commodore machines etc. and to save space in the ROM they just used the BIT instruction to isolate LDA instructions, or other loads. For example:
label_print_CR:
LDA #$0D - carriage return
.byte $2C (BIT instruction op code)
label_print_space:
LDA #$20 - space
.byte $2C
label_print_question_mark:
LDA #$3F - '?'
label_print_character:
main code to print character in A
That would assemble to be:
A9 0D 2C A9 20 2C A9 3F etc..
If you disassemble it you get:
LDA #$0D
BIT $20A9
BIT $3FA9
etc
so the BIT is doing nothing, but it's giving you these cunning specific extra entry points to the routine for printing.
Here's the entry points for the Commodore PET V4.0 BASIC (I don't have the code unfortunately.)
bb1d strout Output String
bb3a outspc Output Format Character
bb41 -Print '<cursor right>'
bb44 -Print '?'
bb46 - Output Character in A
You can clearly see the entry points are just 2-3 bytes apart for 41, 44, 46 so there's no way they're using branches or jumps to load and jump into the general routine.
This application of the BIT instruction is just totally ubiquitous across 6502 machines of that era. I used it in my own code all the time. As you can tell from the disassembly it can be rather confusing as to what they're doing.
This is from the 1976 Microsoft 6502 BASIC listing which you can check out here https://www.pagetable.com/docs/M6502.MAC.txt
DEFINE SKIP1, <XWD ^O1000,^O044> ;BIT ZERO PAGE TRICK.
DEFINE SKIP2, <XWD ^O1000,^O054> ;BIT ABS TRICK.
Note these values are in octal so that's $24 and $2c for the two byte and three byte BIT instructions.
Here's an example:
PARCHK: JSR CHKOPN ;ONLY POSSIBILITY LEFT IS
JSR FRMEVL ;A FORMULA IN PARENTHESIS.
;RECURSIVELY EVALUATE THE FORMULA.
CHKCLS: LDAI 41 ;CHECK FOR A RIGHT PARENTHESE
SKIP2
CHKOPN: LDAI 40
SKIP2
CHKCOM: LDAI 44
;
; "SYNCHK" LOOKS AT THE CURRENT CHARACTER TO MAKE SURE IT
; IS THE SPECIFIC THING LOADED INTO ACCA JUST BEFORE THE CALL TO
; "SYNCHK". IF NOT, IT CALLS THE "SYNTAX ERROR" ROUTINE.
; OTHERWISE IT GOBBLES THE NEXT CHAR AND RETURNS,
;
; [A]=NEW CHAR AND TXTPTR IS ADVANCED BY "CHRGET".
;
SYNCHR: LDYI 0
CMPDY TXTPTR ;CHARACTERS EQUAL?
BNE SNERR
CHRGO5: JMP CHRGET
BIT
is used to check for a flag in bits 6 or 7, check if a number in memory is negative (again, bit 7), to read i/o memory (without destroying registers). It's also used twice as a clever hack to set theV
flag (since there's aCLV
instruction but noSEV
instruction), and once used to hide other instructions.BIT imm
is not a 6502 but a 65C02 instruction.Opcode is $89.