EventHelix.com: CASE Tools; Real-time and Embedded System Design; Object Oriented Design
  Home  |  EventStudio System Designer 4.0  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us

Home > Real-time Mantra > Embedded Design > C to Assembly Translation III
C to Assembly Translation III

This article covers the code generation for if-else and switch statements. We have already covered C function calls and other C statements in previous articles.

Code Generation for If-Else Statement

Code generation for an if-else statement is straight forward. The assembly code exactly mirrors the C code.

Code Generation for If-Else Statement
if (x == y)
{
   z = 1;
}
else
{
   z = 0;
}

    * Move x into Data Register D7
    MOVE.L _x, D7
    * Now compare x with y
    CMP.L _y, D7
    * If not equal branch to the else leg specified by label L1
    BNE.S L1
    * Moving 1 into z
    MOVE.L #1, _z
    * Branch beyond the if-then-else statement
    BRA L2
    * Else portion of the if-else statement
    * Set z to zero
 L1 CLR.L _z
    * End of if-else statement. if portion of the statement executes an 
    * unconditional branch to reach L2. The else leg falls through into L2
 L2 . . .
      

Code Generation for Switch Statement

The code generated for a switch statement varies a lot from one compiler to another. In fact, a given compiler might generate different code in different scenarios. The choice of the code to be generated depends upon the number and range spread of individual case statements.

Different cases of generation of a switch statement are:

Case Values in Narrow Range

If the case values are placed in a narrow range, the compiler can avoid performing a comparison for every case leg in the switch statement. In such cases, the compiler generates a jump table which contains addresses of the actions to be taken on different legs. The value on which the switch is being performed is manipulated to convert it into an index into the jump table. In this implementation, the time taken in the switch statement is much less than the time taken in an equivalent if-else-if statement cascade. Also, the time taken in the switch statement is independent of the number of case legs in the switch statement.

Code Generation for Switch Statement (Case Values are in a Narrow Range)
switch (num)
{
case 3:
   . . .
   break;
   
case 4:
   . . .
   break;
   
case 5:
   . . .
   break;
   
case 6:
   . . .
   break;
}
             * Execution of the switch statement starts with branching to starting
             * point of the switch statement. The switch comparision will be made
             * by instructions at SWITCH_START
             BRA SWITCH_START
             
             
             * The code for handling each case leg of the statement is 
             * shown next. The labels for the beginning of each leg are
             * marked as assembler labels. These labels will be included
             * in a compiler generated switch statement table.
CASE3_LABEL  . . .
             BRA BEYOND
CASE4_LABEL  . . .
             BRA BEYOND
CASE5_LABEL  . . .
             BRA BEYOND
CASE6_LABEL  . . .
             BRA BEYOND
             
             
             * Compiler generates a jump table for the starting address of
             * each case label. This is used in quick indexing to the right
             * option without resorting to cascaded if-else-if statements.
             * Note: Each entry in the jump table is 32 bit address.
CASE_JUMP    DATA.L CASE3_LABEL
             DATA.L CASE4_LABEL
             DATA.L CASE5_LABEL
             DATA.L CASE6_LABEL
             
             
             * Move num into Data Register D7
SWITCH_START MOVE.L _num, D7
             * Subtract the lowest value of the range from D7
             SUBQ.L #3, D7
             * Get the base address of jump table into Address Register A0
             MOVE.L CASE_JUMP, A0
             * Now multiply D7 by 4 to obtain the offset into the jump table
             * Note that the compiler saves a mulitply by using a shift left by 2 bits
             * instruction to implement the muliply by 4
             LSL.L #2, D7
             * Now the offset and jump table base address are used to jump to the
             * appropriate case leg
             JMP 0(A0, D7)
BEYOND       . . .
      

Case Values in Wide Range

If the case legs of the switch statement have a wide deviation in values, the compiler cannot make a jump table to handle the switch statement. In such cases, the jump table would be huge in size and filled very sparingly. Thus the compiler resorts to using a cascade of comparisons to implement the switch. The code generated for the switch statement in such cases will look more like a series of if-else-if statements. Here the time taken to execute the switch statement increases with the number of case legs in the switch.

Code Generation for Switch Statement (Case Values are in a Wide Range)
switch (num)
{
case 1:
   . . .
   break;
   
case 10:
   . . .
   break;
   
case 1000:
   . . .
   break;
   
case 100:
   . . .
   break;
}
             * Execution of the switch statement starts with branching to starting
             * point of the switch statement. The switch comparision will be made
             * by instructions at SWITCH_START
             BRA SWITCH_START
             
             
             * The code for handling each case leg of the statement is 
             * shown next. The labels for the beginning of each leg are
             * marked as assembler labels.
CASE1_LABEL  . . .
             BRA BEYOND
CASE10_LABEL  . . .
             BRA BEYOND
CASE1000_LABEL  . . .
             BRA BEYOND
CASE100_LABEL  . . .
             BRA BEYOND
             
             
             * Move num into Data Register D7
SWITCH_START MOVE.L _num, D7
             * Since the case values are not closely spaced compiler
             * cannot use a jump table. In such cases, cascade of comparison
             * instructions are used.
             * Check if Data Register D7 matches 1
             CMPI.L #1, D7
             * If it matches 1, branch to CASE1_LABEL
             BEQ.S CASE1_LABEL
             * Check if Data Register D7 matches 10
             CMPI.L #10, D7
             * If it matches 10, branch to CASE10_LABEL
             BEQ.S CASE10_LABEL
             * Check if Data Register D7 matches 1000
             CMPI.L #1000, D7
             * If it matches 1000, branch to CASE1000_LABEL
             BEQ.S CASE1000_LABEL
             * Check if Data Register D7 matches 100
             CMPI.L #100, D7
             * If it matches 100, branch to CASE100_LABEL
             BEQ.S CASE100_LABEL
      
BEYOND       . . .      
      

Big Switch Statement with Wide Distribution

If the switch statement has a very large number of case legs and the values are widely distributed, some compilers use binary search to select the case leg. The different case values are sorted by the compiler at compile time for a binary search.

 

  Home  |  EventStudio System Designer 4.0  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us
Copyright © 2000-2008 EventHelix.com Inc. All Rights Reserved.