This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Implementing the switch case.

Hello, 

I am trying to implement the switch case in hand code assembly. From the compiled code I got the following code snippet.

.sect " .switch:my_function"
.clink
$C$SW1: .word $C$L62 ; 0
.word $C$L58 ; 1
.word $C$L20 ; 2
.word $C$L54 ; 3
.word $C$L50 ; 4
.word $C$L45 ; 5
.word $C$L38 ; 6
.word $C$L31 ; 7
.word $C$L24 ; 8
.sect ".text"

My question is to load the label address should the label name start form "$"  ? or it can be start with the alphabet. Also do I need to mention the section and .clink and .text in case of hand coded assembly.

I also tried using the same code in my asm function but it is not working. So the question is how do I load the label address so that I can implement the switch case.

Thanks

unicorn

  • Please refer to the Assembly Language Tools Users Guide for whichever version of the assembler you are using, and whichever device instruction set architecture you are writing for. The ALT User's Guide includes all of the syntax for assembly coding and is the best place to read the details of implementing assembly code.

    The best way to learn assembly code is to write the function in C and keep the assembly output (-k compiler switch). You can read the code to see how the switch structure is implemented (which you appear to have done) and how it is used, which you seem to be asking.

    Like your user name, it is a myth that it is better to write in assembly than in C. When you write in C, turn on optimization, and only consider assembly if the performance is not satisfactory. Even then, it is easiest and most successful if you work from the compiler's assembly output as a starting point and as a learning tool for your assembly training.

    Regards,
    RandyP

  • Hello Randy, 

    Thanks for the reply. In my case the C optimized is not giving the desired result and only in the selective cases I am going for assembly. 

    I am using C66X instruction set. I have referred the TMS320C66x DSP Literature Number: SPRUGH7 November 2010 CPU and Instruction Set, 

    I tried replicating the same assembly code in my hand coded assembly but it was not working.. the label address was not getting loaded correctly for the branch instruction.

    Regards,

    unicorn (The myth) :-)

  • unicorn said:

    My question is to load the label address should the label name start form "$"  ?

    No, This is a convention for the label generated by C compiler but you can name them as you prefer

      Also do I need to mention the section and .clink and .text in case of hand coded assembly.

    Not required. For COFF format, "clink" is used ot inform the linker that the section can be disregarded if not referenced, while have not effect in ELF format.

    Also the ".sect" is not required but if you not change the section the assembler issue a warning since you put data into a .text section.

    I also tried using the same code in my asm function but it is not working. So the question is how do I load the label address so that I can implement the switch case.

    So far I see no reason [that] it should not work. Mybe you can post a little example that show the malfunction.

  • I'll echo Randy's suggestion you reconsider C, especially C with intrinsics.  With a few careful #pragmas, use of the 'restrict' keyword, and so on, you can often do quite well from C.   I've been programming the C6000 family since before its introduction.  I was a hard-core assembly programmer in the beginning.  (I think Randy's seen my work. ;-) )  Now I do just about everything in C and C++.

    If you insist on assembly, though, you might consider the linear assembler.  As I recall, you can't really do a switch-table from linear assembly, but for a switch-case with only 9 cases, you're probably better off doing 8 compares and branches, with a fall-through case.  That's true for hand-coded assembly also.  You can schedule branches in each others' delay slots.

    If the cases in your switch-case are relatively short, you may be better off rewriting the switch-case as a series of if-statements, so they convert to predicated instructions.  (This is true whether you're writing C or assembly.)  The C6x family relies heavily on predicated instructions to reduce costly branching, and you can use this to your advantage.

    For example, consider this imagined example where the 9 cases corresponded to moving one of 8 directions, or staying still:

     
    

    When I compile this, I get a ton of branches. I see the switch table, and a bunch of very shallow cases. The cost to do one "case" is roughly 5 cycles to load the address of the case, 6 cycles to branch to it, and 6 cycles to branch back out at the break, with the case itself hidden in the branch delay--about 17 cycles:


    (note, it goes on like that for all the cases.)


    If I rewrite the above code as a series of if-statements, though, the compiler does much better:

     
    

    becomes

     
    

    That's 10 cycles. And, bonus, it pulled in the return statement to overlap with the code. (I wrote both examples as isolated functions.)  And, of course, for this particular example you could maybe get more clever, but that's getting beyond my original point.

    This suggests that you occasionally need to guide the compiler a bit to your desired solution, but that becomes second nature pretty quickly. Also, C/C++ tends to be much more readable and maintainable, even when transformed like I did above. Imagine coming back to the code in a year. :-)

    switch-case is a particularly ugly one for the compiler, because of the awful semantics of 'break'.  That's C's fault.  Consider a minor tweak to your code and see if you can do better with the compiler.