Calling functions by address
T. William Wells
bill at proxftl.UUCP
Wed Aug 31 20:35:05 AEST 1988
In article <679 at mssx.UUCP> src at mssx.UUCP (Pleschutznig Andreas) writes:
: Suppose following:
:
: We want to write a software emulation for another processor on UNIX
:
: So the main problem is to get into the emulation routines as fast as possible,
: and therefore it doe not seem to be good enough to do
:
: switch (code) {
: case ..
: case ..
: }
:
: So we thought of doing that job by declaring the addresses of the emulation
: routines and jumping to the routines by address like this
:
: (*addressarray[code]);
:
: I know, I know that *does not* work, but maybe there is someone knowing to
: get around.
The correct call is
(*addressarray[code])();
However, you will probably find the switch to be faster.
----
The following analysis presumes that we are running on something
of the order of a Vax, 386, or 68k, and have a reasonable C
compiler.
Here is what the switch is likely to generate:
move a0,code (written in GASM: Generic Assembler)
cmp a0,256
jgrtr after (branch if *unsigned* greater than 256)
shiftl a0,2
jmp table[a0]
The call should generate something like
move a0,code
shiftl a0,2
call table[a0]
and the function should add to this
sub sp,#locals (or something else to make a stack frame)
...
return
The difference between these is:
move a0,code move a0,code
cmp a0,256 shiftl a0,2
jgrtr after call table[a0]
shiftl a0,2 sub sp,#locals
jmp table[a0] return
On the machines I am familiar with, the cmp and sub instructions
are about equivalent in execution time, so leaving out that and
the common instructions, we have:
jgrtr after call table[a0]
jmp table[a0] return
I would expect that the not-taken branch + the indirect branch to
take significantly less time than the call + return. I also have
been *very* generous in my assumptions about how fast the call
will be; it often will have more overhead than the one
instruction I added.
You could also get rid of the cmp and jgrtr instructions, if you
are *certain* that the code passed will always be within range.
Some compilers let you create assembler output instead of object
output; you take that assembler output, run a sed script on it,
and then assemble that. You can use this method to tweak all
sorts of things, besides. But do this only if you are *really*
desperate for speed.
(I wanna #pragma :-)
---
Bill
novavax!proxftl!bill
More information about the Comp.lang.c
mailing list