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.

Wrong values being passed to function in .lib?

Guru 15580 points
Other Parts Discussed in Thread: OMAP-L138

I am calling a function in a linked .lib from my main.c program. My function declaration looks like this: void funct(int32_t x1, int x2). However, when I call this function from c with values x=1 and x2=2 (i.e. funct(1,2)), the values that show up in the .lib function (as seen in the variables window in CCS) are *not* what my main.c function call passed. In fact, they appear to be reversed. What could I be doing wrong?

  • Mike,

    I can't explain why this would be happening. Do you have a test case you can send us to demonstrate the issue?

    Also which version of CCS/CGT is being used?

  • Aarti,

    AartiG said:
    I can't explain why this would be happening. Do you have a test case you can send us to demonstrate the issue?

    Unfortunately I don't. The test case I put together works as expected. The problem happens in my (very large) project which I cannot  post.

    AartiG said:
    Also which version of CCS/CGT is being used?

    CCS V5.1, CGT cl55.

    I suspect it has something to do with 16bit integers, and/or memory model size. Any thoughts? How do the variables get passed to the .lib function?

  • Aarti,

    What does "Unknown register" mean in this snapshot?

    This is one of the variables that is not getting passed correctly.

  • Do you have a matching prototype for funct in main.c before the call site?

  • Arch,

    Yes, I have included the prototypes in a .h file that is included before the call. Each variable in the function call matches the calling function format.

  • Okay, this may seem silly, but are you sure the values are being passed incorrectly?  Do you get the wrong results or is it just that CCS doesn't display them properly?

  • Archaeologist said:
    this may seem silly

    At this point nothing seems silly.....:)

    Archaeologist said:
    are you sure the values are being passed incorrectly?  Do you get the wrong results or is it just that CCS doesn't display them properly?

    As of now, the only variable that is not being passed correctly is the frame_size, which is in the "unknown register". My program checks the passed values against a known range of values an complains if they are not in range....which they are not.

  • Okay, what version of the C5500 compiler (cl55, not the CCS version) are you using?  What command line options?

    My best guess for the unknown register is T3, which is not an argument passing register.

  • Archaeologist said:
    Okay, what version of the C5500 compiler (cl55, not the CCS version) are you using?

      C5500 Compiler Tools 4.4.0 com.ti.cgt.c5500.4.4.win32.feature.group Texas Instruments

    Archaeologist said:
    What command line options?

    -v5515 --memory_model=large -g --include_path="C:/ti/ccsv5/tools/compiler/c5500/include" --include_path="C:/Users/Mike/TI Workspaces/AMX5515/test_library" --include_path="C:/Users/Mike/TI Workspaces/codec Archives/libcodec_C5515/include" --include_path="C:/ti/c55xx_csl/inc" --include_path="C:/Users/Mike/TI Workspaces/codec2 Archives/libcodec2_C5515/libcodec2" --include_path="C:/Users/Mike/TI Workspaces/AMX5515/AMX_5515/inc" --include_path="C:/Users/Mike/TI Workspaces/AMX5515/usbstk5515bsl/include" --include_path="C:/Users/Mike/TI Workspaces/AMX5515/AMX_5515/Debug" --include_path="C:/ti/bios_5_41_11_38/packages/ti/bios/include" --include_path="C:/ti/bios_5_41_11_38/packages/ti/rtdx/include/c5500" --include_path="C:/Users/Mike/TI Workspaces/AMX5515/AMX_5515/Debug" --define="_DEBUG" --define=C55X --display_error_number --diag_warning=225 --ptrdiff_size=16 --algebraic

  • For those reading along, you're using large memory model and DWARF debugging encoding.  The memory model should be irrelevant, because you are not passing any kind of pointer.

    A function of two arguments, one of size 32 bits and one of size 16 bits, will be passed in AC0 and T0 respectively.  Even if the function prototype were void funct(int x2, int32_t x1), the very same registers would be used. It is the responsibility of both the caller and the callee to know the order of parameters so that there is no confusion as to which register contains the first argument.

    The strange message you are getting from CCS is an indication of a problem.  I want to figure out whether it is a bug in CCS or in the compiler.  Since you've said your program doesn't run correctly, this would suggest a bug in the compiler, but I have no idea where to start looking.

    From what point during execution of funct does your screen capture come from?  Is it before or after the parameters have been copied from argument registers to the local stack frame?  Could you show me the disassembly leading up to the call and the disassembly of funct's prolog?  Include enough of the disassembly leading up to the call to show that AC0 and T0 are populated by constant values (or are they?), and enough of the disassembly of funct's prolog to show where AC0 and T0 get copied to (should be an SP-relative memory location).

    Also, if you could post the output of "ofd55 -g funct.obj", or the fragment of that which shows the DW_TAG_subprogram[DW_AT_name=func2] subtree, that might help.

  • Archaeologist said:
    From what point during execution of funct does your screen capture come from?  Is it before or after the parameters have been copied from argument registers to the local stack frame?

    I'm not exactly sure this answers your question, but the screen capture is take immediately after entering the called function in the .lib.

    Archaeologist said:
    Could you show me the disassembly leading up to the call and the disassembly of funct's prolog?  Include enough of the disassembly leading up to the call to show that AC0 and T0 are populated by constant values (or are they?), and enough of the disassembly of funct's prolog to show where AC0 and T0 get copied to (should be an SP-relative memory location).

    I'm not quite sure how to do this. But I can watch the registers in the CCS register window as I step from caller to the callee. Here's what I see.

    1. In my calling code, before the call to the function,  I set x1 = 48000 and x2 = 64. I can see AC0 being set to 48000 (0x000000BB80) and TO is unchanged.

    AC0_HL 0x000000BB80 Core Register

    T0 0x0000 Core Register: Temporary register 0

    2. Immediately upon entering the called function, I can see that AC0_HL is still set to 0x000000BB80, but TO is now set to 0xBB80, and T1 is set to the value of x2 (64).

    T0 0xBB80 Core Register: Temporary register 0
    T1 0x0040 Core Register: Temporary register 1

    Just for clarification, there actually *is* a 3rd variable in the function call. Here is the full format of the function prototype.

    MYSTRUCT *my_function(int32_t x1, int x2, int *error)

    I'm not sure if this 3rd variable is contributing to the problem.

    Is there anything else you would like to see?

    Archaeologist said:
    Could you show me the disassembly leading up to the call and the disassembly of funct's prolog?  Include enough of the disassembly leading up to the call to show that AC0 and T0 are populated by constant values (or are they?), and enough of the disassembly of funct's prolog to show where AC0 and T0 get copied to (should be an SP-relative memory location).

    I would be happy to do this if you need more info. I'll just need instructions on what to do.

  • In large model, those arguments should be being passed in T0, AC0, and XAR0, respectively.

    I suspect you are using C-level debugging; you'll need to use assembly-level debugging by changing the view. I don't have CCS 5.1 installed at the moment, so I can't give you more explicit directions right now. Using assembly-level debugging, you will be presented with a disassembly window, which you should be able to take a screen capture of. You can also use the assembly single-step button. There is potentially a lot of action going on in the function prolog before the debugger will show you the "beginning" of the function in C-level debugging.

    Alternately, you could run the program "dis55" directly on your executable file, which will disassemble the entire program as plain text. Search for your call site by address and search for "funct" by name.

    At this point, the assignment of 0xbb80 to T0 looks fishy, but this might be due to code which converts from int32_t to int in funct, so I can't say for sure that it is a bug.

  • Is this helpful?

            InitCodec:
    026cf8: 4ef7 AADD #-9,SP
    39 int err=NULL;
    026cfa: e60800 MOV #0,*SP(#04h)
    45 sr = 48000;
    026cfd: 3c00 MOV #0,AC0
    026cff: 7ebb8000 OR #48000,AC0,AC0
    026d03: eb0c08 MOV AC0,dbl(*SP(#06h))
    46 spf = 64;
    026d06: e61040 MOV #64,*SP(#08h)
    49 mode = codec_mode_create(sr,spf,NULL);
    026d09: ec318e000000 AMAR *(#00000h),XAR0
    026d0f: a40e MOV *SP(#07h),T0
    026d11: a510 MOV *SP(#08h),T1
    026d13: 6c01d704 CALL codec_mode_create
    026d17: eb3185001332 MOV XAR0,dbl(*(#01332h))
    ============================================================
    err int 0 0x002230@DATA
    spf int 64 0x002234@DATA
    sr long 48000 0x002232@DATA
    ============================================================


    codec_mode_create:
    01d704: 4eeb AADD #-21,SP
    01d706: eb0885 MOV XAR0,dbl(*SP(#04h))
    01d709: c404 MOV T0,*SP(#02h)
    01d70b: eb0008 MOV AC0,dbl(*SP(#00h))
    =============================================================
    Fs long 0x0000BB80 (Hex) 0x002216@DATA
    error int * 0x00000000 0x00221A@DATA
    *(error) int 0 0x000000@DATA
    frame_size int 0xBB80 (Hex) 0x002218@DATA
    
    

    It appears that the undefined register was a CCS abberation. As soon as I stepped into the function, the register was defined.
  • Very helpful.  codec_mode_create is reading the arguments as expected, but InitCodec is not passing them as expected.

    The code is behaving as though the prototype for codec_mode_create seen in InitCode is wrong.  Specifically, it is behaving as if the prototype were "void *codec_mode_create(int, int, void *)".  Please double-check that the prototype for codec_mode_create is present in main.c before the call to codec_mode_create, and that the types in the prototypes have the type you expect.  You may need to use the C preprocessor to see just what the compiler is seeing.  You can add the option -ppo (--preproc_only) to the command line and the compiler will generate a file named main.pp with the results of C preprocessing.

  • Archaeologist said:
    Please double-check that the prototype for codec_mode_create is present in main.c before the call to codec_mode_create

    It is.

    Archaeologist said:
    and that the types in the prototypes have the type you expect

    They are.

    Archaeologist said:
    You can add the option -ppo (--preproc_only) to the command line and the compiler will generate a file named main.pp with the results of C preprocessing.

    I have done this but the file appears to contain only a list of the included .h files. It does show that the .h file that contains the prototype for codec_mode_create *is* included.

    I don't know what else to do. I use this same code on the OMAP-L138 (6748 DSP) and it works flawlessly. I use the same prototype and the same calling format.

    Perhaps we should take this offline so that I can share more of my code.

  • Be aware that in the .pp file, there can be hundreds of blank lines between #include statements, so there may be a lot more stuff later in the file.

    I'd be happy to look at the file (or a part of it) if you want to send it to me as part of a private conversation.  Click my user name to see my profile and then click "Start Conversation".

    At this point, the .pp file would provide the most information.

  • The problem turns out to be that in the header file for the library, a library-specific typedef had a name that indicated it was a 32-bit type, but it was actually defined in terms of "int", which on C55x is a 16-bit type:

    typedef int library_int32;

    I suspected this might be the problem when you said it worked on C6000, where int is a 32-bit type.  For those reading along, the recommended method for defining size-specific types in a portable manner is to include stdint.h and use the types defined there:

    typedef int32_t library_int32;