BIT #imm using the VIC-20 BASIC ROM

Basic and Machine Language

Moderator: Moderators

User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

BIT #imm using the VIC-20 BASIC ROM

Post by chysn »

(mod: follow-up discussion split off from the OP in "ROM calls and other tricks".)

Handy!

Here's a slightly-modified version that you can paste into an .asm file and do things like

Code: Select all

label bit V_80

Code: Select all

V_00 = $C058
V_01 = $C390
V_02 = $C39B
V_03 = $C3A0
V_04 = $C3E7
V_05 = $C01A
V_06 = $C42D
V_07 = $C3A8
V_08 = $C3B9
V_09 = $C414
V_0A = $C377
V_0B = $C06C
V_0C = $C634
V_0D = $C06E
V_0E = $C35C
V_0F = $C563
V_10 = $C338
V_11 = $C08A
V_12 = $C3B3
V_13 = $C44D
V_14 = $C50E
V_15 = $C09C
V_16 = $C67D
V_17 = $C572
V_18 = $C3B1
V_19 = $C67B
V_1A = $C85A
V_1B = $C9C5
V_1C = $C024
V_1D = $C010
V_1E = $C35E
V_1F = $C620
V_20 = $C1A1
V_21 = $C395
V_22 = $C3C5
V_23 = $C03A
V_24 = $C360
V_25 = $C33A
V_26 = $C048
V_27 = $C022
V_28 = $C40B
V_29 = $C459
V_2A = $C087
V_2B = $C534
V_2C = $C030
V_2D = $C4B0
V_2E = $C02C
V_2F = $C670
V_30 = $C00C
V_31 = $C3BC
V_32 = $C3BE
V_33 = $C40F
V_34 = $C409
V_35 = $C33C
V_36 = $C5D2
V_37 = $C07E
V_38 = $C3BF
V_39 = $C052
V_3A = $C02A
V_3B = $C33E
V_3C = $C5A9
V_3D = $C7BB
V_3E = $C3FD
V_3F = $C59D
V_40 = $CB5A
V_41 = $C008
V_42 = $C005
V_43 = $C004
V_44 = $C0A8
V_45 = $C09E
V_46 = $C092
V_47 = $C0C1
V_48 = $C136
V_49 = $C00A
V_4A = $C02E
V_4B = $C0FC
V_4C = $C0BE
V_4D = $C006
V_4E = $C09F
V_4F = $C0A2
V_50 = $C08F
V_51 = $C160
V_52 = $C034
V_53 = $C009
V_54 = $C0AA
V_55 = $C0AF
V_56 = $C040
V_57 = $C0E5
V_58 = $C056
V_59 = $C118
V_5A = $C098
V_5B = $C3C8
V_5C = $DBC8
V_5D = $C044
V_5E = $CAB4
V_5F = $C3C3
V_60 = $C3B7
V_61 = $C036
V_62 = $C77D
V_63 = $CA17
V_64 = $C032
V_65 = $C072
V_66 = $C779
V_67 = $C002
V_68 = $C068
V_69 = $C081
V_6A = $C344
V_6B = $C49D
V_6C = $C437
V_6D = $CE78
V_6E = $CE7B
V_6F = $CA5E
V_70 = $C020
V_71 = $C05E
V_72 = $C346
V_73 = $C48B
V_74 = $C715
V_75 = $CA57
V_76 = $C475
V_77 = $CDE0
V_78 = $C000
V_79 = $C080
V_7A = $C04E
V_7B = $C086
V_7C = $C070
V_7D = $C05A
V_7E = $CA2A
V_7F = $C03C
V_80 = $C018
V_81 = $C393
V_82 = $C026
V_83 = $C362
V_84 = $C3BD
V_85 = $C046
V_86 = $C486
V_87 = $CAC0
V_88 = $C3EC
V_89 = $C92F
V_8A = $C3B0
V_8B = $C076
V_8C = $C514
V_8D = $C511
V_8E = $C65A
V_8F = $CFAE
V_90 = $C34A
V_91 = $C3EA
V_92 = $D3EB
V_93 = $D377
V_94 = $C060
V_95 = $C422
V_96 = $DF1C
V_97 = $C881
V_98 = $C3CD
V_99 = $C5A1
V_9A = $C683
V_9B = $C042
V_9C = $DF31
V_9D = $C34C
V_9E = $C05C
V_9F = $C01E
V_A0 = $C389
V_A1 = $CEAC
V_A2 = $C413
V_A3 = $C0B1
V_A4 = $C014
V_A5 = $C396
V_A6 = $C57C
V_A7 = $C933
V_A8 = $C12C
V_A9 = $C44A
V_AA = $C142
V_AB = $C140
V_AC = $C32A
V_AD = $C074
V_AE = $C7EB
V_AF = $C143
V_B0 = $C3D7
V_B1 = $C06A
V_B2 = $C038
V_B3 = $C096
V_B4 = $C603
V_B5 = $C32C
V_B6 = $D51B
V_B7 = $CBDE
V_B8 = $C50B
V_B9 = $C522
V_BA = $C04A
V_BB = $C93F
V_BC = $C14C
V_BD = $C14B
V_BE = $C016
V_BF = $C9C8
V_C0 = $C5BE
V_C1 = $C0AB
V_C2 = $C0D5
V_C3 = $C04C
V_C4 = $C0A0
V_C5 = $C0D0
V_C6 = $C043
V_C7 = $C00F
V_C8 = $C00D
V_C9 = $C01D
V_CA = $C03D
V_CB = $C015
V_CC = $C01B
V_CD = $C011
V_CE = $C09A
V_CF = $C091
V_D0 = $C019
V_D1 = $C028
V_D2 = $C0A3
V_D3 = $C039
V_D4 = $C073
V_D5 = $C354
V_D6 = $C079
V_D7 = $C071
V_D8 = $C031
V_D9 = $C063
V_DA = $C088
V_DB = $C08B
V_DC = $C053
V_DD = $C3A4
V_DE = $C144
V_DF = $C05F
V_E0 = $C061
V_E1 = $C033
V_E2 = $C067
V_E3 = $C001
V_E4 = $C003
V_E5 = $C093
V_E6 = $C4E6
V_E7 = $C661
V_E8 = $C090
V_E9 = $C5D4
V_EA = $C062
V_EB = $CFDC
V_EC = $C078
V_ED = $C064
V_EE = $C968
V_EF = $C95D
V_F0 = $C334
V_F1 = $C4BA
V_F2 = $C3F9
V_F3 = $C925
V_F4 = $C461
V_F5 = $C5C0
V_F6 = $D0B9
V_F7 = $C012
V_F8 = $C529
V_F9 = $C3EE
V_FA = $C41B
V_FB = $C548
V_FC = $C523
V_FD = $C60A
V_FE = $C512
V_FF = $C336
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
Noizer
Vic 20 Devotee
Posts: 297
Joined: Tue May 15, 2018 12:00 pm
Location: Europa

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Noizer »

Mike wrote: ↑Thu Oct 22, 2020 9:33 am (...)
Very useful, can save some zero-Page addresses for another use if +1 byte and +1 cycle are irrelevant for the individual purpose πŸ‘. Nice exercise searching all those bytes with Basic. I would have run a simple assembler Hunt command for the value needed
Valid rule today as earlier: 1 Byte = 8 Bits
-._/classes instead of masses\_.-
User avatar
Mike
Herr VC
Posts: 4842
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Mike »

Noizer wrote:Very useful, can save some zero-Page addresses for another use if +1 byte and +1 cycle are irrelevant for the individual purpose πŸ‘.
Would you care to provide a specific code example where the technique highlighted in the OP saves on zeropage usage?
Nice exercise searching all those bytes with Basic. I would have run a simple assembler Hunt command for the value needed
Yes.
User avatar
Mike
Herr VC
Posts: 4842
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Mike »

chysn wrote:Handy!
We were somewhat lucky though: one of the byte values only occurs exactly once in the BASIC ROM. Also, the list is the same for the original BASIC ROM and my bug-fixed version.

If there had been one or more byte values missing, or the list had been different for the two BASIC versions, that would have quite diminished its use.
Here's a slightly-modified version that you can paste into an .asm file and do things like [...]
Good idea! In a symbolic assembler the list helps to abstract from the specific addresses in the VIC-20 BASIC ROM. When a program using that technique is ported to the C64 (or other 65xx computers for that matter), only that list needs to be changed to adapt the "BIT #imm" instances. :)

Of course one could still include the values within the own code (which makes it more portable, no question). Even if that now leads to absolute address references of the BIT instructions within my relocate tool - it could always still relocate itself. :wink:
wimoos
Vic 20 Afficionado
Posts: 348
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by wimoos »

Mike wrote:The most interesting values are probably the powers of 2, they're given here:

Code: Select all

$01  $C390
$02  $C39B
$04  $C3E7
$08  $C3B9
$10  $C338
$20  $C1A1
$40  $CB5A
$80  $C018
In character ROM, at location $8268 is a list of powers of two in descending order, and at $8270 in ascending order.
These lists make it also to easy to convert a bitnumber in X into a bitmask in A:

Code: Select all

LDA $8270,X
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
Mike
Herr VC
Posts: 4842
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Mike »

wimoos wrote:In character ROM, at location $8268 is a list of powers of two in descending order, [...]
viewtopic.php?t=952&start=60&hilit=8268 ... :wink:

Unfortunately, the NMOS 6502 doesn't feature a corresponding BIT ABS,X instruction that could be put to use here (it's available on the 65C02 though).
wimoos
Vic 20 Afficionado
Posts: 348
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by wimoos »

Another thing to note is that BIT# in 65C02 does not modify N or V, but only Z.
Where in 6502 the BIT instructions do set N and V corresponding B7 and B6 of the memory location

Regards,

Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
User avatar
Noizer
Vic 20 Devotee
Posts: 297
Joined: Tue May 15, 2018 12:00 pm
Location: Europa

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Noizer »

Mike wrote: ↑Thu Oct 22, 2020 1:19 pm
Noizer wrote:Very useful, can save some zero-Page addresses for another use if +1 byte and +1 cycle are irrelevant for the individual purpose πŸ‘.
Would you care to provide a specific code example where the technique highlighted in the OP saves on zeropage usage?

OK, then here's an example shown the differences of using ...
- BIT ZeroPage (size 2 bytes, execution speed 3 clock cycles)
- BIT ABSolute / aka BIT#imm (3 bytes, 4 clock cycles)

The purpose of the following simple code snipplets is to process some data stored somewhere in a memory page and write back to another buffer page in ram. It's nothing special. πŸ™„
In the main loop I used the addressing mode "LDA / STA zero page indirect indexed in Y", which is more flexible in overall use than the absolute,Y addr. mode, IMHO.

So for start I would write...

1) Using BIT $ zp

Code: Select all

	total bytes, not counting "setup": 16
....................................... .  .   .    .     .
	"loop" execution time in clock cycles: 
		(23*256)-1	(22*256)-1 
		=5887		=5631
.........................................
label	opcode		branch	branch
			skipped	taken
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
setup	LDY #$00
	LDX #$77
	LDA #$A0
	STY $FA
	STX $FB
	STY $FC
	STA $FD
zpini	LDA #$20		
	STA $AA		
loop	LDA ($FA),Y	5	5
	BIT $AA		3	3
	BEQ storea	2	3
	LSR		2	
storea	STA ($FC),Y	6	6
	INY		2	2
	BNE loop	3	3
...	... next action
//////////////\\\\\\\\\\\\\\\\\\\\\\\
2) Using BIT $ abs (surrogate for BIT# imm), as suggested from Mike and Chysn in the OP:

Code: Select all

"setup" as code #1, "zpini" left out because not needed anymore:
....................................... .  .   .    .     .
	total bytes, not counting setup: 13
	loop execution time: 
		(24*256)-1	(23*256)-1
		=6143		=5887
.........................................
label	opcode		branch	branch
			skipped	taken
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
loop	LDA ($FA),Y	5	5
	BIT $C1A1 (=$20)4	4
	BEQ storea	2	3
	LSR		2	
storea	STA ($FC),Y	6	6
	INY		2	2
	BNE loop	3	3
	... next action
//////////////\\\\\\\\\\\\\\\\\\\\\\\
Conclusion:
Using BIT xxx in this example (if all calculations are rightπŸ˜…) performs:
1) BIT zp -> "loop" size + "zpini": 16 Bytes, average execution time: 5759 clock cycles
2) BIT ABS -> "loop" size: 13 Bytes, average execution time: 6015 clock cycles (+ ~3,5 raster lines more than #1)

It's as usually a matter of time memory trade off.
Recognize and know the choices. πŸ˜™
wimoos wrote: ↑Fri Oct 23, 2020 1:59 am Another thing to note is that BIT# in 65C02 does not modify N or V, but only Z.
Where in 6502 the BIT instructions do set N and V corresponding B7 and B6 of the memory location
Regards,
Wim.
BTW: since vic 20 still carries a 6502 CPU, are comments to an 65C02 nice to know, but may not always be necessary.
However, if this is considered important and inspiring, πŸ˜ƒ
we could start another topic "Instruction set comparison from 8-Bit Systems".
Valid rule today as earlier: 1 Byte = 8 Bits
-._/classes instead of masses\_.-
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: BIT #imm using the VIC-20 BASIC ROM

Post by chysn »

wimoos wrote: ↑Fri Oct 23, 2020 1:59 am Another thing to note is that BIT# in 65C02 does not modify N or V, but only Z.
Where in 6502 the BIT instructions do set N and V corresponding B7 and B6 of the memory location
That's an interesting note. I quite like BIT's usual N and V flag behavior. It's nice to have a couple bits that you can always check in situ, and the N bit 7 is especially useful for checking flags. But I can't think of a reason to check bits of immediate mode operands, so the 65C02's exception makes sense.
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: BIT #imm using the VIC-20 BASIC ROM

Post by chysn »

Noizer wrote: ↑Fri Oct 23, 2020 6:50 am Conclusion:
Using BIT xxx in this example (if all calculations are rightπŸ˜…) performs:
1) BIT zp -> "loop" size + "zpini": 16 Bytes, average execution time: 5759 clock cycles
2) BIT ABS -> "loop" size: 13 Bytes, average execution time: 6015 clock cycles (+ ~3,5 raster lines more than #1)

It's as usually a matter of time memory trade off.
Recognize and know the choices. πŸ˜™
I get what you're saying. The portability and clarity of your approach also can't be totally ignored.

For the instruction SizeOf subroutine, using ersatz immediate BIT breaks the portability of the subroutine, which is a harsh penalty as there are lots of 6502 machines that could make use of it. In the original version, I used AND instead of BIT, and reset A with TYA after each test, which was portable but used all three registers. Obviously it's a fine thing to have options.

These considerations become all the more acute when one is trying cram a subroutine into the user vector space!
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
Noizer
Vic 20 Devotee
Posts: 297
Joined: Tue May 15, 2018 12:00 pm
Location: Europa

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Noizer »

chysn wrote: ↑Fri Oct 23, 2020 11:10 am (...) In the original version, I used AND instead of BIT, and reset A with TYA after each test, which was portable but used all three registers. Obviously it's a fine thing to have options. (...)
Oh yes, Iβ€˜m sure you got that.
The importance of the BIT command becomes particularly clear when there is not even time or memory for a TYA, in the own rules and targets of coding that piece of byte sequences
Valid rule today as earlier: 1 Byte = 8 Bits
-._/classes instead of masses\_.-
User avatar
Mike
Herr VC
Posts: 4842
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Mike »

Noizer wrote:- BIT ZeroPage (size 2 bytes, execution speed 3 clock cycles)
The slight speed advantage (surely important inside a loop) is well noted, but while you were counting beans you forgot it takes another two instructions (LDA #imm/STA ZP, 4 bytes) to put the value into zeropage.
chysn wrote:[...] using ersatz immediate BIT breaks the portability of the subroutine [...]
Funnily enough it was your suggestion to use ROM values in the other thread. ;)

I still think the approach is in order for the executable program. In the source however, it should be commented where the mask values come from, that's what I did. If someone wants to port the tool over to another 65xx machine he has all necessary information in the source. In case one or more mask values aren't there in the ROM of the other machine (unlikely), it is still possible to append the values after the BRK instruction, and direct the BIT instructions there, preserving the original idea of the implementation with BIT ABS.
chysn wrote:[...] I can't think of a reason to check bits of immediate mode operands, [...]
BIT ABS on a RTS instruction (which should be readily available in a surrounding program, opcode $60) is a fairly known method to substitute the 'missing' SEV instruction.
User avatar
chysn
Vic 20 Scientist
Posts: 1205
Joined: Tue Oct 22, 2019 12:36 pm
Website: http://www.beigemaze.com
Location: Michigan, USA
Occupation: Software Dev Manager

Re: BIT #imm using the VIC-20 BASIC ROM

Post by chysn »

Mike wrote: ↑Sun Oct 25, 2020 3:58 am
chysn wrote:[...] using ersatz immediate BIT breaks the portability of the subroutine [...]
Funnily enough it was your suggestion to use ROM values in the other thread. ;)

I still think the approach is in order for the executable program.
Oh, yeah, me too. Breaking portability isn't a reason to avoid the technique in a VIC-20 program. I can see myself doing this in a game or other application with regularity. Memory saving outweighs cycle saving for what I do.
chysn wrote:[...] I can't think of a reason to check bits of immediate mode operands, [...]
BIT ABS on a RTS instruction (which should be readily available in a surrounding program, opcode $60) is a fairly known method to substitute the 'missing' SEV instruction.
What would be the reason for removing the N/V-setting behavior for BIT's immediate mode only? Was it just an oversight on the 65C02 die, or does it make something easier? My view of processor flags is that you don't need to be too careful with them. I'll usually check flags within a few instructions of where they're set, so if they get set as side effect of an instruction, I usually won't care.
VIC-20 Projects: wAx Assembler, TRBo: Turtle RescueBot, Helix Colony, Sub Med, Trolley Problem, Dungeon of Dance, ZEPTOPOLIS, MIDI KERNAL, The Archivist, Ed for Prophet-5

WIP: MIDIcast BASIC extension

he/him/his
User avatar
Mike
Herr VC
Posts: 4842
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by Mike »

chysn wrote:What would be the reason for removing the N/V-setting behavior for BIT's immediate mode only? Was it just an oversight on the 65C02 die, or does it make something easier?
I'd say they did it on purpose. Copying N/V from the constant(!) immediate operand would not constitute a bit *test* at all, in the sense there are no 'surprises' to expect in the outcome.

Unlike the C flag, N and V also do not serve as input to any of the arithmetic/logic instructions so that's even one reason less to set N and V to known values. The only exception being CLV, which is mainly there to allow a "BVC *" spin test of the SO pin - this facility is used in the 1541 by the floppy controller to signal a byte has been read from disk.
wimoos
Vic 20 Afficionado
Posts: 348
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: BIT #imm using the VIC-20 BASIC ROM

Post by wimoos »

Mike wrote: ↑Sun Oct 25, 2020 8:13 am Copying N/V from the constant(!) immediate operand would not constitute a bit *test* at all, in the sense there are no 'surprises' to expect in the outcome.
Hmm, thinking about this: loading a register with an immediate value DOES set N and Z (many BEQ/BNE or BMI/BPL depend on this). Or, setting(clearing) N after an LSR for that matter.

So, setting N and V in BIT# wouldn't have been that inconsistent.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
Post Reply