#317 [Z80] Suggest optimisation for function pointer calls

z80 port (30)

This is a request/suggestion for an optimisation. It is Z80-specific, but I'm not sure if this comes under the Z80 port for the code generation or the peephole optimiser for later.

When this is compiled using "sdcc -mz80 -c func_call.c":

===== func_call.c =====
extern int myfunc(void *);

typedef struct ops_s {
int (*funcA)(void *);
int (*funcB)(void *);
} ops_t;

ops_t ops = { myfunc, myfunc };

call_func(ops_t *ops, void *arg)
return (ops->funcB(arg));
===== end func_call.c =====

It produces the following assembler for the function call at the end:

1: push hl
2: ld hl,#00103$
3: push hl
4: ld l,c
5: ld h,b
6: jp (hl)
7: 00103$:

If a library function were provided such as this:

jp (hl)

we could then better write this as:

1: push hl
2: ld l, c
3: ld h, b
4: call _jump_to_hl

The return from the called function would be directly to line "5:", whatever that is.

This eliminates 1 label, 2 instructions (occupying 4 bytes, although overall only 1 is actually saved), and would benefit from eliminating the same instruction elsewhere within the program (with a space saving dependent upon how frequently it is used). It also saves time (T states as recorded in the Zilog Z80 CPU User's Manual):

ld de,#label$ ; 3 bytes, 10 Tstates
push de ; 1 byte, 11 Tstates
jp (hl) ; 1 byte, 4 Tstates
; Total: 5 bytes, 25 Tstates

call _jp_to_hl ; 3 bytes, 17 Tstates

__jp_to_hl:: ; Library include
jp (hl) ; 1 byte, 4 Tstates

; Total: 4 bytes, 21 Tstates

Again, the time saving overall is dependent upon how frequently this construct is used.

I personally first saw this technique of calling a jump in the Spectrum +3 manual (chapter 8 part 27, where it used "call jumptoit/jp(iy)" to call into DOS), and also in the +3DOS ROM, where a call to a particular location in a jump block allowed the implementation of DOS to change, but the caller still called the jp instruction, and the ret would return directly to the caller.

It seems here that there is both a space and time saving to be had by using this, but I'll log this for discussion if nothing else.


  • Maarten Brock

    Maarten Brock - 2011-04-12

    This is no bug, but a request for an optimization. Therefor I moved it.

    NB: This is already implemented on mcs51 (for functions without parameters due to the calling convention) in crtcall.asm.

  • Maarten Brock

    Maarten Brock - 2011-04-12
    • labels: 100692 --> z80 port
  • Maarten Brock

    Maarten Brock - 2011-04-13
    • assigned_to: nobody --> maartenbrock
    • status: open --> closed
  • Maarten Brock

    Maarten Brock - 2011-04-13

    Implemented in SDCC 3.0.2 #6428.


Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.

No, thanks