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.

*.asm / *.lst files generated in build and code composer

Hey, I have a question regarding the listing and asm files that can be generated in a build. It appears that the assembly code in these files does not exactly match the output, when debugging with code composer. I am using version 4.6.4 of the TI ARM Optimizing C/C++ Compiler and code composer v3.3 to build for an ARM7 target. When debugging with code composer it looks like some move instructions end up becoming add immediate value of 0. Basically, I'm counting on the listing files to be an exact representation of what's happening in assembly code, but this doesn't appear to be the case. Here is the code in question:
   Listing snipit C code - Some_Function( arg1, arg2, (val1+val2) );
   3806 000007b4 18D2              ADD       A3, A3, A4            ; val1 + val2
   3807 000007b6 1C29              MOV       A2, V2                  ; Move arg2 to proper register
   3808                    $C$DW$376       .dwtag  DW_TAG_TI_branch
   3809                            .dwattr $C$DW$376, DW_AT_low_pc(0x00)
   3810                            .dwattr $C$DW$376, DW_AT_name("Some_Function")
   3811                            .dwattr $C$DW$376, DW_AT_TI_call
   3812 000007b8 F7FF!             BL        Some_Function     ; Call function
   Turns into
   ADD R2, R2, R3  ; Updates flags in C code, but not asm (must use ADDS)
   ADD R1, R5, #0   ; Uses add immediate 0 for register to register operation
   BL Some_Function

As far as I can tell, there are critical differences between these instructions. Namely, the MOV instruction doesn't update the overflow flag (why should it), but the ADD instruction does. I'm confused by this also, since the flags should not be updated unless the S suffix (ADDS) is used. This appears to happen anywhere in C code, but not in assembly. ie. ASM(" ADD R1, R5, #0"); updates flag, the same code in a .asm file doesn't. Note: it doesn't matter whether inline assembly is used or the compiler generates code, the flag updates.

Any help sorting out my confusion here would be greatly appreciated. Are the listing files not an accurate representation of the ASM code generated? Is there something I'm missing about the ARM7 architecture and the ADD/MOV instructions? Is there any reason that flags seem to update unconditionally in C code, but not assembly?

  • Well, this is a long story, and the short version is that you should update your TI ARM compiler to the latest version.

    ARM defined a Unified Assembly Language (UAL) syntax which specifies exactly what the syntax looks like for instructions that set syntax (the S is always explicit), and the most recent TI ARM compiler and assembler use and enforce this syntax. In particular, it gives an error on the asm statement you show:

    "c.asm", ERROR! at line 9: [E0002] Instruction must set status
    ADD R1, R5, #0

    When not in UAL mode, the TI compiler uses the TI-style syntax for assembly; in particular, the S (for set status) is implicit unless it is needed for disambiguation.

    You may find that the behavior when using the --ual compiler and assembler option in older releases (including 4.6.4) to make more sense, but there are still some holes.

    Listing files do have the exact opcode used, but the assembly code shown is what came in as input, either what the user typed or what the compiler generated. There are many instructions that are pseudo-instruction shorthands, such as MOV actually encoding as ADD #0. The same holds true for the disassembler; you may be seeing pseudo-instructions.

  • I believe you are comparing the listing file to the disassembly view. They will not match exactly. The compiler uses some pseudo instructions and registers which the disassembly view will display differently. Let's handle this as two different issues:

    1. The status setting ADD issue

    There are few details I'll need to fully understand your example, but I think I can get pretty close. On ARM7 there are two modes, ARM and Thumb mode, which have different instructions and rules on which instructions set status. From your example I think you are using thumb mode. Another issue is the assembly mode being used. The assembler supports UAL (Unified Assembly Language) and non-UAL modes. UAL is an update ARM made to the assembly language specification a while back. In non-UAL mode the TI assembler is pretty relaxed when it comes to specifying the 'S'. So ADD r2,r2,r3 will be assembled as ADDS r2,r2,r3. Compiler versions prior to 5.0 used non-UAL mode to generate assembly code, so the S was omitted and inline assembly could omit it as well. Starting with 5.0 the compiler emits UAL syntax. To .thumb and .arm directives put the assembler into UAL mode. The .state16 and .state32 directives put the assembler into non-UAL mode. I don't know why specifying the ADD in an assembly file isn't setting status, but one guess would be that you assembled in ARM mode.

    2. The MOV instruction

    The issue with allow MOV A2,V2 without the S is again related to UAL vs. non-UAL mode. The only way to accomplish a low register to low register move in Thumb mode is to set status. Now, there isn't really a MOVS instruction for low registers in the hardware. The TI and GCC ARM compilers use ADDS <Rd>, <Rm>, #0 to accomplish a MOV and the ARM (Keil) compiler uses LSLS <Rd>,<Rm>,#0. Either one will work, however the latest Architecture reference manual does say to encode MOVS as LSLS. 

    Let me know if you have any follow up questions.

  • Thank you so much for the answer. I will definitely follow up if I have additional questions, but I think everything I need is in your answer.
  • Thank you, I though I was going crazy. I was not aware that they were pseudo-instructions, but did kind of wonder. I've run into pseudo-instructions on other architectures, but not ARM. This is not related to the actual coding issue; It was apparent what was actually happening. I just needed to know this for future analysis.