DSPRelated.com
Forums

Strange behaviour of the C compiler for the TMS320C5000. Ideas?

Started by Dimitar Penev July 21, 2004
Hello Friends, 

I would like to share a problem which I am tiring to resolve already
half an day without success.

So I am writing C program for the tms320c5509 using CCS 2.21. 
I am using dynamical memory allocation quite intensively. 

My target which I am using to test my code has only 2 LEDs and one
button so the thing
which I am doing is tracing of the execution flow by switching on one
of the LEDs at certain places inside the code.
So testing the code like this I observed that after the lines below
something strange happens

int *direction_map; 
bsize=mw * mh; // bsize == 64 
direction_map = (int *)malloc(bsize * sizeof(int)); 

several lines after execution of this code and the LED can not be
switched on.
So I decided to try debugging using the simulator (C55xx Functional
Simulator)

The result of the line above is unexpectedly for me: direction_map
become 64.
In fact it is incorrect since my heap base address is 0x8000 

I noticed that actually the result of malloc is equal to the input
argument I am passing.

My program up to here only allocates memory (doesn't free) so I expect
that there is not
granulation of the heap. Following this thinking I've checked the
pointer returned by the previous
memory allocation (last malloc before the problematic malloc ) (I use
malloc quite often in this program) and
taking into account the heap size and base address I am pretty sure
that there is still plenty of
free heap. Then I decided to check the assembly code generated by the
problematic lines.
And it was surprise for me that the malloc uses T0 register to return
the address. It is not
according to the rule of using of the registers for passing and
returning the arguments during
function call. 



0001a0 85 
500 0001a1 20 NOP ; avoids Silicon Exception CPU_90 
501 0001a2 20 NOP ; avoids Silicon Exception CPU_90 
502 .line 21 
503 ;----------------------------------------------------------------------
504 ; 226 | bsize = mw * mh; // bsize== 64 
505 ; 228 | // THIS IS THE PROBLEMATIC PLACE!!!! 
506 ;----------------------------------------------------------------------
507 0001a3 A516 MOV *SP(#11), T1 ; |226| 
508 0001a5 D314 MPYM *SP(#10), T1, AC0 ; |226| 
0001a7 05 
509 0001a8 C02A MOV AC0, *SP(#21) ; |226| 
510 .line 26 
511 ;----------------------------------------------------------------------
512 ; 231 | direction_map = (int *)malloc(bsize * sizeof(int)); 

TMS320C55x COFF Assembler PC Version 2.56 Wed Jul 21 00:15:45 2004 

Tools Copyright (c) 1996-2002 Texas Instruments Incorporated 
maps.asm PAGE 12 

513 ;----------------------------------------------------------------------
514 0001aa A42A MOV *SP(#21), T0 ; |231| 
515 0001ac 6C00 CALL #_malloc ; |231| 
0001ae 0000! 
516 ; call occurs [#_malloc] ; |231| 
517 0001b0 2240 MOV T0, AC0 
518 0001b2 EB1C MOV AC0, dbl(*SP(#14)) 
0001b4 08 

I check the assembly code generated by the compiler for the other
malloc in my program and there
everything is OK. For the output pointer one of XARx is used. 


So the behavior of the problematic line is explainable for me based on
the assembly code. It is clear now
why the 64 is returned (T0 is used for the input and then for the
returned pointer). So the direction_map
points in the memory mapped register area (MMR) and it is not
surprising why the system crashes after
some modification in this area. 

It is interesting that if I substitute a simple function with
prototype ( void *func(size_t) exactly the same as
the malloc the assembly code is again correct (XAR0 is used for the
output pointer)

So, it seems to me that it as a bug in a compiler or hopefully I am
missing something. Unfortunately I just don't
see way to resolve it. 

Probably somebody will help me to continue? 
All suggestions are wellcome! 

Best Regards 
penev
Hello,
most unpleasure from mine with CCS work was the fact that compiler not
to insert all 'nop' are needed for pipeline. Thus variables haven't
new value without any warning.
 I turn on 'Mixed codes' to watch assembler text into 'C'. In
suspicion cases divide C-line to 2-3 ones or substitute by " asm ... "
lines.

Cheers
On 21 Jul 2004 04:26:16 -0700, dpenev@yahoo.com (Dimitar Penev) wrote
in comp.dsp:

> Hello Friends, > > I would like to share a problem which I am tiring to resolve already > half an day without success. > > So I am writing C program for the tms320c5509 using CCS 2.21. > I am using dynamical memory allocation quite intensively. > > My target which I am using to test my code has only 2 LEDs and one > button so the thing > which I am doing is tracing of the execution flow by switching on one > of the LEDs at certain places inside the code. > So testing the code like this I observed that after the lines below > something strange happens > > int *direction_map; > bsize=mw * mh; // bsize == 64 > direction_map = (int *)malloc(bsize * sizeof(int)); > > several lines after execution of this code and the LED can not be > switched on. > So I decided to try debugging using the simulator (C55xx Functional > Simulator) > > The result of the line above is unexpectedly for me: direction_map > become 64. > In fact it is incorrect since my heap base address is 0x8000 > > I noticed that actually the result of malloc is equal to the input > argument I am passing. > > My program up to here only allocates memory (doesn't free) so I expect > that there is not > granulation of the heap. Following this thinking I've checked the > pointer returned by the previous > memory allocation (last malloc before the problematic malloc ) (I use > malloc quite often in this program) and > taking into account the heap size and base address I am pretty sure > that there is still plenty of > free heap. Then I decided to check the assembly code generated by the > problematic lines. > And it was surprise for me that the malloc uses T0 register to return > the address. It is not > according to the rule of using of the registers for passing and > returning the arguments during > function call.
[snip] You are casting the return value of malloc() to pointer to int. If you get a compiler error when you remove the cast, it means one of two things: 1. You are compiling as C++. 2. You are compiling as C, but you have not included <stdlib.h> in this particular source module to have a proper prototype for malloc() in scope. I don't know this particular TI DSP or the calling conventions of its compiler, but some TI compilers use different registers for passing and returning pointers compared to integer values. If you don't have a prototype for malloc() in scope, the compiler must assume it returns an int, and since you case the returned value to int *, it accepts it. This causes the compiler to generate code to take whatever value is in the integer return register and convert it into a pointer. If there is a valid pointer (or NULL) in the register used to return pointers, the compiler is ignoring it due to the lack of prototype. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html