Patriek, Thanks very much for all those useful tips.
I'm hoping to put together a tip sheet with example code for newbie Z80 programmers like myself. I'd like to include your ideas, do you mind? Many thanks, Tony > -----Original Message----- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]On Behalf Of Patriek > Lesparre > Sent: Saturday 20 October 2001 4:29am > To: [EMAIL PROTECTED] > Subject: Re: Z80 loops > > > Tony Bedford wrote: > >I have a loop that needs to clear a 4096 byte area. > >I would like it to be as fast as possible, but this is > >not critical. > > Even if you do not use a LDIR like suggested already, your routine is > pretty inefficient. I'll give you a faster version, so you can > learn a few > simple tricks. > I'll comment your original listing: > > ; need to clear data area > ; data area is 4096 bytes > ; 4096 = (255*16)+16 ;; 256*16 is better, see > following > > ld hl,DATA_AREA > ld c,16 > > @@start_loop1: > > ld b,0 ; making b 0 will loop 256 times > ; this is because b is decreased > BEFORE it's > ; checked for 0. > > xor a ; use A register to store 0 > value, this will > ; increase effeciency by 3*256 cycles > > ; by the way, you can do 'xor a' and then 'ld b,a' to save > ; an additional 3 cycles. > > @@clear_byte: > ld (hl),a ; so use A here, not 0. > inc hl > djnz @@clear_byte > > dec c > jp nz,@@start_loop1 > > The rest of the routine was unnecessary. (since we already looped > 256 times) > > >Any suggestions? Does anyone know of any good docs on Z80 code > >optimisation? > > There's just a few small tricks and the rest is 'common sense' (which > highly depends on ones natural talent for logic). > > In stead of 'LD A,0' use 'XOR A'. > > In stead of 'CP 0' use 'OR A'. If you have a list of CP's and don't need > the value tested you can use: > or a ; in stead of CP 0 > jr z, its_0 > dec a ; in stead of CP 1 > jr z, its_1 > dec a ; in stead of CP 2 > jr z, its_2 > etc... > > If you need the sign-flag of A, don't do a PUSH AF/POP HL or whatever > construct. You can just use 'OR A' or 'AND A'. I usually use 'AND A' to > distinguish between 'CP 0' and 'evaluate flags' use. > > For multiplication and division try to use bitshifts and ADDs. General > purpose multiply/divide routines are often unnecessarily slow. > a * 40 for instance: > ld l,a > ld h,0 > add hl,hl ; hl = a * 2 > add hl,hl ; hl = a * 4 > add hl,hl ; hl = a * 8 > ld e,l > ld d,h > add hl,hl ; hl = a * 16 > add hl,hl ; hl = a * 32 > add hl,de ; hl = a * 32 + a * 8 = a * 40 > > Don't forget the shadow set of registers. EX AF,AF' to > temporarily save the > A register is much (MUCH!) faster than PUSH/POP AF. > Also EX DE,HL is often very valuable: > ; shift left 32 bit value HLDE > ex de,hl > add hl,hl > ex de,hl > adc hl,hl > > Well, I probably forgot a few other tricks, maybe I'll post them if I > remember them. > > Greetz, > Patriek > > -- > For info, see http://www.stack.nl/~wynke/MSX/listinfo.html > -- For info, see http://www.stack.nl/~wynke/MSX/listinfo.html
