|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
copy bits in a byte
Posted: Tue Apr 13, 2021 8:17 pm
|
after swap two bits in a byte, today I'm wondering if there's a (fast) way to copy a bit into a few (but not all) other locations into the same byte, for instance as in:
%abcdefgh -> %abCCefCh bonus point if it's possible to do that with more than one bit at the same time, as in: %abcdefgh -> %BBCCefCB any hints? :) |
|
|
How to replace select bits with contents of CF
Posted: Tue Apr 13, 2021 10:04 pm
|
Assume bit C is in CF, and byte %abcdefgh is in B.
sbc a ; A=C C C C C C C C xor b ; A=CaCbCcCdCeCfCgCh and %00110010 ; A=0 0 CcCd0 0 Cg0 clear bits to keep from B xor b ; A=a b C C e f C h I'll attempt the bonus point if it is explained where bits B and C come from, so that I can get them into CF and apply the above. For more inspiration, see ASM Snippets and Optimizing assembly code. (These pertain to SM83, a CPU by Sharp that is similar in many ways to Z80.) |
|
|
Posted: Wed Apr 14, 2021 9:34 am |
thanks for the reply and the links!
sorry for not stating the question correctly. I mean the bits come from the same byte as in %76543210 -> %76553250 or in %76543210 -> %66553256 (also, is last operation an XOR? Shouldn't it be OR?) |
|
|
copy bits in a byte
Posted: Wed Apr 14, 2021 11:41 am
|
The fastest and most space-efficient way I found was to test one bit being copied at a time using the BIT instruction and then using an OR or AND with immediate data to set or clear the target bits in one go:
CopyBit6:
BIT A,6 JR NZ, SetBits7and0 AND %01111110 JR CopyBit5 SetBits7and0: OR %10000001 CopyBit5: BIT A,5 JR NZ, SetBits4and1 AND %11101101 JR exit SetBits4and1: OR %00010010 Usually, using the direct register logical instructions is the fastest way to do something like this because the instructions involved (LD, OR, AND, RRCA, RLCA) are all single bytes and all fast instructions. But the single Accumulator kills it because you end up copying back and forth from temp values in another register or two multiple times. The bit test, set and reset instructions (BIT, SET, RES) are purpose built for this, but as they all have a 0xCB prefix byte, they take the most time, and the most space, all due to the prefix byte. There may be faster and better ways though. |
|
|
Posted: Wed Apr 14, 2021 12:00 pm |
The XOR is correct here. His suggestion makes use of the fact that using XOR you can combine 2 values in a non-destructive way: If C = A XOR B then A = C XOR B and B = C XOR A. In the row xor b ; A=CaCbCcCdCeCfCgCh
Each bit in register A stores the original bit (a..h) and the value of C. That's what he illustrated in the comment. Using the AND he then clears the information in the bits that should not keep the value of C. The final XOR then writes the original bits to the bits that got masked out to 0 and removes the original bit from this bits that still contain the XOR-combined value, leaving C in there. It's basically the same idea as with swapping the values of two variables using XOR. |
|
|
Posted: Wed Apr 14, 2021 12:28 pm |
Given that the objective is to copy bit 5 to the other bits, the first step is to copy bit 5 into CF.
ld a, %11011111 and b ; A = B if bit 5 were 0 cp b ; CF = 1 if A < B, 0 if A == B Then proceed as above to overwrite selected bits with CF. In total, it takes 9 bytes and 34 cycles. |
|
|
Posted: Wed Apr 14, 2021 12:53 pm |
instead of copying the single bit to CF and then from there to all the bits in the accumulator (that wouldn't work in a single pass if we were going to copy more than one bit to any other location) how could we combine that to less instructions?
say we want to go from %76543210 to %76673223 - sure we don't want to do the whole copy process 4 times, one for each bit, right? also, thanks @Calindro for the clarification, much appreciated! :) |
|
|
copy bits in a byte
Posted: Wed Apr 14, 2021 2:55 pm
|
For all out speed, my boring solution is 10 bytes and 27 to 29 cycles per bit copied.
What's the optimisation for out of interest? |
|
|
Posted: Thu Apr 15, 2021 3:30 am |
This snippet takes advantage of moving two of the bits by the same distance (1 place value) and two other bits by the same distance (3 place values).
; have %hgfedcba, want %hgghdccd
ld a, b ; A=h g f e d c b a rra ; A=? h g f e d c b xor b ; A=?hhggffeeddccbba and %00100010 ; A=0 0 gf0 0 0 cb0 xor b ; A=h g g e d c c a ld b, a rrca ; A=b h g g e d c c rrca ; A=c b h g g e d c rrca ; A=c c b h g g e d xor b ; A=chcgbghegdgcecda and %00010001 ; A=0 0 0 he0 0 0 da xor b ; A=h g g h d c c d |
|