|
Post by minsoft on Aug 19, 2021 16:14:13 GMT -5
I want to do something very simple but I'm not sure the best way to do it...
I have a byte with just one bit set, and I want to 'rotate' it right one place at a time
10000000 01000000 00100000 00010000 00001000 00000100 00000010 00000001
Easily done with LSR, but for the next shift I want it to start again, ie 10000000. I thought I could do it with ROR but of course that uses the carry flag which could be set or not in this case.
I've got it to work like this, but surely there is a better way?:
LSR mybyte BNE skip LDB #%10000000 STB mybyte skip:
|
|
|
Post by Malban on Aug 20, 2021 4:47:26 GMT -5
Dunno is this is MUCH better... lsr mybyte bcc noCarry ror mybyte noCarry
---
Hm, actually it is NOT, it only looks better because of one instruction less. Cycle wise this is the same (10 cycles or 17 cycles, when not branching).
You can gain a couple of cycles when using the DP register...
|
|
|
Post by minsoft on Aug 20, 2021 5:23:09 GMT -5
Thanks Malban, I will probably leave it then. I just wanted to be sure I wasn't missing something as I'm not 100% confident with all of the instructions.
It isn't too cycle critical where I am using it, just seemed like quite a lot of cycles for something so 'simple'.
|
|
|
Post by gtoal on Aug 21, 2021 4:27:47 GMT -5
This was a real stumper. I couldn't find a shorter 8-bit rotate, but I did come up with a solution which (I think) avoids a branch (if it's correct). But it's rather silly...
lda #$80 ldb data ; 01 2 4 8 10 20 40 80 pshu b mul ; 0:80 1:0 2:0 4:0 8:0 10:0 20:0 40:0 C=0 for all stb tmp ; B = 80 0 0 0 0 0 0 0 rolb ; A:B = C=1, 0:0 C=0, 1:0 2:0 4:0 8:0 10:0 20:0 40:0 adca tmp ; A = 81 1 2 4 8 10 20 40, C=0 for all sta tmp pulu a ; A = 1 2 4 8 10 20 40 80 -81 -1 -2 -4 -8 -10 -20 -40 sbca tmp ; A = 80 1 2 4 8 10 20 40
(tmp might be avoided with a pshs and ,s+ access)
I hope I got this right, the whole thing above came from working backwards from the instruction table below, of sub, or sbc with c=0: 02 - 01 -> c=0 01 04 - 02 -> c=0 02 08 - 04 -> c=0 04 10 - 08 -> c=0 08 20 - 10 -> c=0 10 40 - 20 -> c=0 20 80 - 40 -> c=0 40 01 - 81 -> c=1 80
I guess I ought to assemble this and check it but there's little point as no-one would ever use it even if it worked...
|
|
|
Post by kokovec on Aug 21, 2021 12:34:34 GMT -5
Yet another variant:
start: lda #%10000000 loop1: lsra bcc loop1 bra start
|
|
|
Post by Peer on Aug 26, 2021 10:08:09 GMT -5
If you have some rom space to waste:
Define 256 rom byte copies "mybyte_0" to 2mybyte_255", starting on a page boundary, containing consecutively 32 times the constant pattern 1000000, 01000000, 00100000, 00010000, 00001000, 00000100, 00000010, 00000001.
Then define a pointer "mybyte_ptr" in ram and assign to it the rom space address of "mybyte_0".
To "shift" just increase the low byte of the pointer:
"inc mybyte_ptr+1" (7 cycles, 1-byte integer arithmetics will ensure that the pointer remains within the data field defined above)
And to access the value use indicrect addressing, e.g.:
"ldb [mybyte_ptr]" (9 cycles)
Yes, this is trading rom space for run-time efficiency, but this should be faster than any of the other methods. I guess ...
Cheers, Peer
|
|
|
Post by minsoft on Sept 8, 2021 6:43:04 GMT -5
Thanks the interesting alternative ideas!
I just used my original version, since it isn't too cycle critical. I have 32 bytes of data as faux-inputs for the demo in my game. I'm using 2 bits per 'frame'* and am using this byte (mybyte in my example) to keep track of which bit of the current demo data byte to use. So this code is only used during the demo, once every 8 frames.
(* not game frame, the inputs are repeated for 8 game frames)
|
|