<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Sun, 17 Jul 1994 19:40:54 EST
From   : Stephen Quan <quan@...>
Subject: 256 branches in C.

Hi everyone.  I have two parallel BBC emulators in the works and both
of the are finally getting some perfomance (I switch C compilers :-).
One thing is getting me down, however, which nearly makes me opt for
assembly is the difficulty of creating 256-branch instructions.

Currently, I have :

    switch (opcode)
    {
      case 0x00 : ....
      case 0x01 : ....
      case 0x02 : ....
      .... 
      case 0xff : ....
      default :
        break;
    }

and unless if you have the optimiser on, you will get terrible code from
the above.  ie. the assembly language looked something like :

             LDA opcode
             CMP #&00
             BNE .try_0x01
             ....
.try_0x01    LDA opcode
             CMP #&01
             BNE .try_0x02
             ....
.try_0x02

Which means if you had opcode 0xff, the emulator will waste a lot of time
finding your instruction.  I have seen some compilers optimise the very
same C code to :

             JMP (choice_table,opcode)
.choice_0x00 ...
.choice_0x01 ...
.choice_0x02 ...
.choice_0x03 ...
....
.choice_0xff ...

.choice_table EQUW choice_0x00
.choice_table EQUW choice_0x01
.choice_table EQUW choice_0x02
.choice_table EQUW choice_0x03
.choice_table EQUW choice_0x04

However, the assembly code it generates is not quite as short or as
simple as the above.  It does a fair amount of messing about with
choice_table and opcode, before it finally decides to jump to the
right place.  Overall the performance is improved (8 times!), but
there could be just that little more improvement.

I have tried to force the C compiler to do better, and have been
trying to find a better command than switch, I have tried things
like

    main()
    {
      char *opcode_table[256]; /* 256 array of labels. */
      int   opcode;

      opcode_table[0x00] = opcode_00; /* assigning labels to the array. */
      opcode_table[0x01] = opcode_01;
      opcode_table[0x02] = opcode_02;
            :
      opcode_table[0xff] = opcode_ff;

            :

    main_cpu_loop:
      opcode = fetch_opcode();
      goto opcode_table[opcode]; /* jump to a label depending on opcode. */

    opcode_00 : ....  goto main_cpu_loop;
    opcode_01 : ....  goto main_cpu_loop;
    opcode_02 : ....  goto main_cpu_loop;
    opcode_03 : ....  goto main_cpu_loop;
        :
    }

Unfortunately, I cannot find any C syntax that gets to anything
close to the above.  Any suggestions???
-- 
Stephen Quan (quan@...                 ), SysAdmin, Analyst/Programmer.
Centre for Spatial Information Studies, University of Tasmania, Hobart.
GPO BOX 252C, Australia, 7001.  Local Tel: (002) 202898 Fax: (002) 240282
International Callers use +6102 instead of (002).
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>