Welcome, Guest. Please login or register.


Author Topic: 19% faster LDIR (Read 3699 times)

Offline BruceTanner

  • EP lover
  • *
  • Posts: 607
  • Country: gb
19% faster LDIR
« on: 2014.December.02. 12:28:30 »
Here's a trick I didn't know about/had never thought of. I can't claim credit for it: I've just come across it at http://map.grauw.nl/articles/fast_loops.php.

Basically it's unrolling LDIR into a series of LDIs. Easy if you know in advance how many bytes but here's some general copy code that's nearly 20% faster (with a little overhead). It's self-modifying so won't work in ROM!

Code: [Select]
;
; Up to 19% faster alternative for large LDIRs (break-even at 21 loops)
; hl = source (“home location”)
; de = destination
; bc = byte count
;
FastLDIR:
    xor a
    sub c
    and 16 - 1
    add a,a
    di
    ld (FastLDIR_jumpOffset),a
    ei
    jr nz,$  ; self modifying code
FastLDIR_jumpOffset: equ $ - 1
FastLDIR_Loop:
    ldi  ; 16x LDI
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    ldi
    jp pe,FastLDIR_Loop
    ret

I'm not sure why the di and ei are needed unless you're going to use the same code in an interrupt routine and main code.

Offline Zozosoft

  • Global Moderator
  • EP addict
  • *
  • Posts: 14722
  • Country: hu
    • http://enterprise.iko.hu/
Re: 19% faster LDIR
« Reply #1 on: 2014.December.02. 12:38:04 »
I think it is commonly used :-) Prodatron also want to do similar for SD card reading.

Another faster solution the POP/PUSH trick, my example (it is scrolling half screen, left 320 pixel column of 640 pixel wide screen):
Code: ZiLOG Z80 Assembler
  1.                 LD HL,4000H          
  2.                 LD DE,4000H-9*80+20  
  3.                 LD A,198              
  4.                 CALL SPSCROLL1        
  5.                 LD HL,4000H-9*80      
  6.                 LD DE,4000H+189*80+20
  7.                 LD A,9              
  8. SPSCROLL1  
  9.                 LD (SPCEL+1),DE      
  10.                 LD (SPCOUNT+1),A      
  11.                 LD (SPSAVE+1),SP      
  12. SPKEZD:        
  13.                 LD SP,HL              
  14.                 POP BC                
  15.                 POP DE                
  16.                 POP HL                
  17.                 POP IX                
  18.                 POP IY                
  19.                 EXX                  
  20.                 POP BC                
  21.                 POP DE                
  22.                 POP HL                
  23.                 POP AF                
  24.                 EX AF,AF'            
  25.                 POP AF                
  26.                 LD (SPKEZD2+1),SP    
  27. SPCEL:          LD SP,4000H-9*80+20  
  28.                 PUSH AF              
  29.                 EX AF,AF'            
  30.                 PUSH AF              
  31.                 PUSH HL              
  32.                 PUSH DE              
  33.                 PUSH BC              
  34.                 EXX                  
  35.                 PUSH IY              
  36.                 PUSH IX              
  37.                 PUSH HL              
  38.                 PUSH DE              
  39.                 PUSH BC              
  40.                 LD HL,40              
  41.                 ADD HL,SP            
  42.                 LD (SPCEL2+1),HL      
  43.  
  44. SPKEZD2:        LD SP,4000H
  45.                 POP BC
  46.                 POP DE
  47.                 POP HL
  48.                 POP IX
  49.                 POP IY
  50.                 EXX
  51.                 POP BC
  52.                 POP DE
  53.                 POP HL
  54.                 POP AF
  55.                 EX AF,AF'
  56.                 POP AF
  57. SPCEL2:         LD SP,4000H-9*80+20
  58.                 PUSH AF
  59.                 EX AF,AF'
  60.                 PUSH AF
  61.                 PUSH HL
  62.                 PUSH DE
  63.                 PUSH BC
  64.                 EXX
  65.                 PUSH IY
  66.                 PUSH IX
  67.                 PUSH HL
  68.                 PUSH DE
  69.                 PUSH BC
  70.                 LD HL,80
  71.                 ADD HL,SP
  72.                 LD (SPCEL+1),HL
  73.                 LD HL,(SPKEZD2+1)
  74.                 LD BC,80-20
  75.                 ADD HL,BC
  76. SPCOUNT:        LD A,200
  77.                 DEC A
  78.                 LD (SPCOUNT+1),A
  79.                 JR NZ,SPKEZD
  80. SPSAVE:         LD SP,0
  81.                 RET

Offline BruceTanner

  • EP lover
  • *
  • Posts: 607
  • Country: gb
Re: 19% faster LDIR
« Reply #2 on: 2014.December.02. 12:46:16 »
I think it is commonly used
Oh, I must be 30 years out of date :oops: sorry to show my age! :smt087

Offline Prodatron

  • EP user
  • *
  • Posts: 256
  • Country: de
  • Back on the Z80
    • http://www.symbos.de
Re: 19% faster LDIR
« Reply #3 on: 2014.December.02. 15:20:39 »
I really like it, when you sometimes refresh your Z80 knowledge by looking again at nice tricky routines! :)
The DI and EI is for making this routine re-entrance able: After an EI the interrupts are still locked for one more command, so the self-modified JR won't be disturbed.