CPI / CPIR instruction

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
R-Tape
Site Admin
Posts: 2535
Joined: Thu Nov 09, 2017 11:46 am

CPI / CPIR instruction

Post by R-Tape » Thu Sep 26, 2019 7:02 pm

Has anyone ever actually used these instructions?

I remember when I first read about them in 'Spectrum Machine Language for the Absolute Beginner', and it described them as being so powerful as to leap skyscrapers (or something). They really do sound like they have the potential to be as useful as LDI/LDIR, but every time I think "Ah! Finally - I can use CPI!*", there's a property of it that means it's not the best solution.

I think if it was a CP (HL) with (DE), increment, and DEC BC then I'd find a use for it.

*which was the case this week
0 x

User avatar
Ast A. Moore
Dynamite Dan
Posts: 1190
Joined: Mon Nov 13, 2017 3:16 pm

Re: CPI / CPIR instruction

Post by Ast A. Moore » Thu Sep 26, 2019 8:41 pm

Yes, I use CPIR it in my redefine keys routine. It’s pretty slow, so I’d reserve it for when code execution speed isn’t a concern.

I think its primary purpose is for use with data arrays, i.e. text, etc. I use it to ignore the already defined keys (something many redefine keys routines neglect, much to the chagrin of players).
0 x
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.

Ralf
Dynamite Dan
Posts: 1284
Joined: Mon Nov 13, 2017 11:59 am
Location: Poland

Re: CPI / CPIR instruction

Post by Ralf » Thu Sep 26, 2019 9:33 pm

I very rarely use it. But I used it once in one of my games. Imagine a table of N bytes. I needed to count how many bytes in this table are 0.
Eventually I did:

Code: Select all

 LD HL,TableStart
 LD DE,0                ;count of 0s
 LD BC,TableSize
 XOR A
Loop1:
 CPI                    ;does CP (HL) INC HL DEC BC
 JP NZ,Loop2
 INC DE                 ;increase count of 0s
Loop2
 JP PE,Loop1
0 x

catmeows
Berk
Posts: 34
Joined: Tue May 28, 2019 11:02 am

Re: CPI / CPIR instruction

Post by catmeows » Thu Sep 26, 2019 9:59 pm

R-Tape wrote:
Thu Sep 26, 2019 7:02 pm
Has anyone ever actually used these instructions?
No, I usually try to find things by faster way than by CP*(R).

Seriously, aren't the instructions rather slow ?

AFAIK native LZ packers use the CPIR/CPDR as fast way to find match candidate.
0 x

User avatar
Seven.FFF
Manic Miner
Posts: 339
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: CPI / CPIR instruction

Post by Seven.FFF » Fri Sep 27, 2019 3:08 am

It’s very useful for writing expression parsers. Finding the CR end of line markers, finding the equals in Key=Value constructs, reading data out of modem AT command responses, that kind of thing.
0 x
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
seven-fff.com/blog

User avatar
R-Tape
Site Admin
Posts: 2535
Joined: Thu Nov 09, 2017 11:46 am

Re: CPI / CPIR instruction

Post by R-Tape » Fri Sep 27, 2019 1:21 pm

Thanks guys. You've made me realise there is somewhere I could (and should) have used this. I had a map of 18 bytes and I needed to find the first available empty place, so a new tile could be inserted.

For the first time ever I will use the CPIR instruction!
catmeows wrote:
Thu Sep 26, 2019 9:59 pm
Seriously, aren't the instructions rather slow ?
The speed looks quite good to me, same as LDI/LDIR. CPI/R seem less likely to be used in fast game loops anyway.
0 x

User avatar
Ast A. Moore
Dynamite Dan
Posts: 1190
Joined: Mon Nov 13, 2017 3:16 pm

Re: CPI / CPIR instruction

Post by Ast A. Moore » Fri Sep 27, 2019 1:23 pm

R-Tape wrote:
Fri Sep 27, 2019 1:21 pm
I had a map of 18 bytes and I needed to find the first available empty place, so a new tile could be inserted.
Yup. That is precisely where you’d use CPI/CPIR.
0 x
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.

catmeows
Berk
Posts: 34
Joined: Tue May 28, 2019 11:02 am

Re: CPI / CPIR instruction

Post by catmeows » Fri Sep 27, 2019 2:35 pm

R-Tape wrote:
Fri Sep 27, 2019 1:21 pm
The speed looks quite good to me, same as LDI/LDIR. CPI/R seem less likely to be used in fast game loops anyway.
Well, LDI decreases/increases 3 16bit registers, does one memory read, one memory write.
CPI decreases/increases 2 16bit registers, does one memory read and register comparison.
I was just thinking about that yesterday when I was trying to figure out why I don't use CPI etc.

Btw. Whenever I needed some buffer that would have empty slots, I kept an user stack with pointers to empty slots as a helper structure. That way an empty slot is always on top of stack so I just pick it up. When I invalidate data in slot, I return the slot pointer on top of stack.
0 x

Joefish
Manic Miner
Posts: 621
Joined: Tue Nov 14, 2017 10:26 am

Re: CPI / CPIR instruction

Post by Joefish » Fri Sep 27, 2019 3:37 pm

I could have used it in my compression routine, for looking to see if a data byte is already recorded in a dictionary of most common values. Except I want an 8-bit index into the dictionary, not an absolute address, so it's easier to just write my own compare routine than faff around with adjusting the answer from an absolute address to a relative value. And no, I'm not going to align everything to page boundaries!
0 x

User avatar
R-Tape
Site Admin
Posts: 2535
Joined: Thu Nov 09, 2017 11:46 am

Re: CPI / CPIR instruction

Post by R-Tape » Fri Sep 27, 2019 8:47 pm

catmeows wrote:
Fri Sep 27, 2019 2:35 pm
Well, LDI decreases/increases 3 16bit registers, does one memory read, one memory write.
CPI decreases/increases 2 16bit registers, does one memory read and register comparison.
I was just thinking about that yesterday when I was trying to figure out why I don't use CPI etc.
Ah sorry, I see what you mean. I rarely think in terms of tstates and had to resort to Rodney Zaks.

To summarise:

Code: Select all

LDI	16t

equivalent to:
	ld a,(hl)	;7t
	ld (de),a	;7t
	inc hl		;6t
	inc de		;6t
	dec bc		;6t
	=32t

CPI	16t

equivalent to:
	cp (hl)		;7t
	inc hl		;6t
	dec bc		;6t
	=19t
I'm exposing my ignorance here, but can anyone explain why they have the same number of tstates, but one is clearly doing a lot more than the other?

(It might be easiest just to say "wiring" :mrgreen:)

EDITED - removed stupid flowery prose
0 x

Post Reply