Page 1 of 1

Finding LSB in a register

Posted: Thu Jan 17, 2019 12:14 pm
by arkannoyed
Hey folks, I'm back!

I'm currently shaving more bytes off the Chess display engine (it got down to 589 bytes last year!). A few fresh ideas to explore after a break from it. I've speeded it up a little so far, which is nice, but I've an idea that requires to find the LSB within HL. Is there a quick method anyone knows of?

Ta.

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 12:21 pm
by arkannoyed
I should've also added that I want to isolate that BIT and set all the bits to the Right of it ideally.

I know that you could just DEC HL which will set all to the right, but clearing the rest, is there an easy way? 8 bit maths is easy, 16 bit less so.

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 1:17 pm
by Ast A. Moore
Not sure if this is fast enough for you, but I came up with this:

Code: Select all

;HL holds the value for testing

	ld de,0
	push hl
	ld b,16
l1	rrc h		;mind the C in RRC here.
	rr l
	jr c,p1
	ccf
	rl e
	rl d
	djnz l1

p1
	pop hl
	add hl,de
The DJNZ loop can be replaced with a simple jump, if you’re positive that at least one bit in HL is set. As a bonus, though, B will hold the position of the first set bit counting from the left (if you need it).

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 1:26 pm
by arkannoyed
Interesting. Whichever way I've tried so far, its coming out a lot more complicated than I'd originally imagined.

Basically this is an auto masking excercise, where I want to create a mask by using the LSB as the marker for where to create the mask, so for instance;

if HL were;

00000101 11000000 then bit 6 of L is the marker and would make a mask say in BC of 00000000 00111111

does that make sense?

It does need to be small, and speed isn't massively important, more the smallness!

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 1:40 pm
by Ast A. Moore
arkannoyed wrote: Thu Jan 17, 2019 1:26 pm It does need to be small, and speed isn't massively important, more the smallness!
In that case, my routine can be modified to save one byte: replace LD B,16 with LD B,D or LD B,E. You’ll end up with having to LD A,B/NEG/INC A to get the first set bit position (now counting from the right) in A.

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 2:19 pm
by Metalbrain
What about this?

Code: Select all

;Input:  DE = original value
;Output: HL = mask

		ld	hl,0
		and	a
nextbit:	adc	hl,hl
		ret	c
		rr	d
		rr	e
		ccf
		jr	c,nextbit
		ret

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 3:02 pm
by arkannoyed
Oooh, yes. Now the RET C won't be needed, as theres no need for error protection (I think thats what its there for?), though I will need to push and pop DE, but that just might work. Off to test thanks!

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 3:05 pm
by Metalbrain
arkannoyed wrote: Thu Jan 17, 2019 3:02 pm Oooh, yes. Now the RET C won't be needed, as theres no need for error protection (I think thats what its there for?), though I will need to push and pop DE, but that just might work. Off to test thanks!
I was about to post that the RET C could be removed, but it's not for error protection, just to exit earlier in the case of initial value being 0

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 3:10 pm
by Ast A. Moore
Oh, I see. You only want the mask, not the already masked value. Sorry, I didn’t get that from your initial posts. Disregard my code then.

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 3:49 pm
by Kweepa
No loops:
ld bc,hl
dec bc
ld a,h
xor 255
and b
ld b,a
ld a,l
xor 255
and c
ld c,a
Just uses HL & BC

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 9:47 pm
by Kweepa
Mine is 13 bytes (checked with www.asm80.com, which is awesome!).
Metalbrain's is 12 bytes, if you remove the ret c and replace ld hl,0 with xor h/xor l.

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 9:54 pm
by djnzx48
Could you replace XOR 255 with CPL and get it down to 11 bytes?

Re: Finding LSB in a register

Posted: Thu Jan 17, 2019 9:58 pm
by Kweepa
Yep, that works :)
Didn't know about that instruction!

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 12:32 am
by djnzx48
If you're doing regular AND-then-OR masking, you can just use OR B instead of CPL: AND B (and the same for C) as it doesn't matter what the mask is when the pixel value is set. That would get it down to 9 bytes.

(EDIT: Actually in that case all you need to create the mask is a single DEC instruction. So this method only requires one byte.)

Maybe other types of masking would work, for instance OR for the mask and then XOR for the sprite. Are you doing the same thing to create a mask on the left using the MSB?

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 7:58 am
by Metalbrain
Kweepa wrote: Thu Jan 17, 2019 9:47 pm and replace ld hl,0 with xor h/xor l.
xor h/xor l wouldn't set hl to 0, they would just make A = A xor H xor L

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 9:16 am
by arkannoyed
Wow, some great ideas, and it certainly looks as if the 8 bit logic methods will win. I'll have a go with some ideas later and see what works best.

Lots of re-designing to do to make the printing byte-wise work as opposed to bit-wise, which is how the Chess pieces are done currently. The speed improvement will be huge though, and hopefully might lose a few bytes as well as a bonus!

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 9:42 am
by lister_of_smeg
Kweepa wrote: Thu Jan 17, 2019 3:49 pm No loops:
ld bc,hl
dec bc
ld a,h
xor 255
and b
ld b,a
ld a,l
xor 255
and c
ld c,a
Just uses HL & BC
ld bc,hl isn't a valid z80 instruction

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 9:46 am
by arkannoyed
yes, but ld B,H and ld C,L are, which does the same thing.

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 2:01 pm
by arkannoyed
Seems to almost do what it needs to. The only thing left that I should've mentioned before is that it needs to RESet the LSB in HL (the data register).
So whereas maybe HL=05c0h, after creating the mask, bit 6 of L needs to be cleared, giving the result HL=0580h.

Does that make sense?

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 3:19 pm
by Kweepa
arkannoyed wrote: Fri Jan 18, 2019 9:46 am yes, but ld B,H and ld C,L are, which does the same thing.
Wow, apparently asm80.com is too clever for its own good - it automatically converted ld bc,hl to ld b,h/ld c,l!

Re: Finding LSB in a register

Posted: Fri Jan 18, 2019 3:22 pm
by lister_of_smeg
arkannoyed wrote: Fri Jan 18, 2019 2:01 pm Seems to almost do what it needs to. The only thing left that I should've mentioned before is that it needs to RESet the LSB in HL (the data register).
So whereas maybe HL=05c0h, after creating the mask, bit 6 of L needs to be cleared, giving the result HL=0580h.

Does that make sense?
This any good?

Code: Select all

ld	d, h
ld	e, l
dec	de
ld	a, d
xor	h
ld	d, a
cpl
and	h
ld	h, a
ld	a, e
xor	l
ld	e, a
cpl
and	l
ld	l, a
rr	d
rr	e