We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
For the '51 compilers/linkers evaluate which data/idata slots can be overlaid. I have to save 3 slots to make room for a new feature. Is there a way to make the linker show the tree in a less cryptic way than by module (i.e. by function) ? Have fun, Erik
Graham provides a marvelous discussion of how to optimize your program. I'll add a few more bits to what he said. The compiler uses registers for function arguments. This is always faster because the caller can store the argument values into registers rather than into memory. The C51 compiler passes at most 3 arguments in registers according to some rules that are defined in the Compiler User's Guide in Chapter 3. The register allocation scheme is fixed (there is nothing random about it) and is well-defined. Since there are only 8 1-byte registers, at most 8 bytes of arguments may be passed. The order of the argument is of paramount importance in register allocation, and, simply changing the order of the arguments (that have different types) may cause the compiler to place more or fewer arguments in registers. This is an exact science, so refer to the manual for details. As far as Global Register Optimization, the comment, this does mean that 'leaf' functions - functions that do not call other functions - are much more likely to make good use of registers that 'branch' functions is not exactly true. The assumption is that all functions destroy all register contents. So, a calling function must save and restore the contents of any registers it needs after a function call. Fortunately, in C, this does not cause a great deal of problems. Global register optimization maps out which registers are used in each function. This allows a calling function to avoid saving and restoring some registers. It doesn't do a lot in small programs, but in larger programs that have a lot of functions, this optimization helps. Jon
First, thanks for the info/advice. Second, I was looking for a function - short of perusing assembler output, which I am very capable of - to tell me not what module, but which function the maximum "load" happened in. One obstacle I'm up against is that I am trying to fix something in inherited code which is not organized in a way I would do it. Thanks again, and if you have a method of listing (I)DATA use by function, not mudule, please let me know. Erik
In the uVision2 Browser, could you check just DATA or IDTATA in 'Memory Spaces', and just 'Data' for 'Filter On' You can then click on the column heading (as in WinExplorer) to sort by, eg, 'Uses'. This would show you which variables in (I)DATA are used the most/least. But I can't see a simple, direct way to get to what you want. :-( Maybe a couple of passes with GREP or similar through the listing & map files, with all the symbol & cross-ref options enabled?
Below is an excerpt from a .M51 linker map file. Teh segment names listed in the left column are composed of three fields which indicate the segment time (PR for code in this case), function name, and module name. The column to the right indicates how much RAM that each segment (function) is using. Is this not what you're looking for?
OVERLAY MAP OF MODULE: test (MAIN) SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?C_C51STARTUP ----- ----- +--> ?PR?MAIN?MAIN +--> ?C_INITSEG ?PR?MAIN?MAIN ----- ----- +--> ?PR?FOO?MAIN ?PR?FOO?MAIN 0008H 0004H +--> ?PR?BAR?MAIN
David, what you show is by MODULE (source file) not by single function. I want to know by function. Andy, I do not use uVision, I use Codewright as an editor and run the compiler from huge batchfiles. I have not seen a means of "batchfiles" in uVision. Thanx, Erik
what you show is by MODULE (source file) not by single function. I want to know by function No, What David shows IS by function. It is NOT shown by module. OVERLAY MAP OF MODULE: test (MAIN)
SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?C_C51STARTUP ----- ----- +--> ?PR?MAIN?MAIN +--> ?C_INITSEG ?PR?MAIN?MAIN ----- ----- +--> ?PR?FOO?MAIN ?PR?FOO?MAIN 0008H 0004H +--> ?PR?BAR?MAIN
Ok, sorry BUT: (edited for space) ?PR?_SEN?UPC 0036H 0004H +--> ?PR?WAI?UPX +--> ?PR?_WRI?UPXA +--> ?PR?FIN?UPX +--> ?PR?DEC?UPCD +--> ?PR?_PAU?FQ1 SEN uses 2 bytes of DATA, which of the rest is using 4 ? That, Horatio, is the question.
What are the arguments and local variables of this function and what are their data types? Jon
We are way past the subject: "WHICH of the functions sharing this (I)DATA space is the one that uses the full count". Of course I know what the local variables are, but when 47 functions share the same space it is quite tedious to look at all 47 to find out which one to analyze to see if you can find a workaround to reduce (I)DATA use. The abbreviated list in my posting 2 levels up represent a page of functions sharing the same (I)DATA space not just 4 Erik
We are way past the subject: "WHICH of the functions sharing this (I)DATA space is the one that uses the full count". Of course I know what the local variables are, but when 47 functions share the same space it is quite tedious to look at all 47 to find out which one to analyze to see if you can find a workaround to reduce (I)DATA use. The abbreviated list in my posting 2 levels up represent a page of functions sharing the same (I)DATA space not just 4 I you misunderstand the information that is presented in the call tree. The LENGTH is NOT the length of the DATA space used by the functions that are called. It is the size of the function indicated. Perhaps an example will help clarify this:
#pragma NOREGPARMS // Don't put arguments in registers long func_2 (long x) { long a, b, c, d; /*** 16 + 4 bytes = 20 bytes ***/ a = 1; b = 2; c = 3; d = 4; return (x + a + b + c + d); } long func_1 (long x) { long a, b, c; /*** 12 + 4 bytes = 16 bytes ***/ a = 11; b = 12; c = 13; return (x + a + b + c + func_2 (105)); } void main (void) { long a; /*** 4 bytes ***/ a = func_1 (100); while (1); }
SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?C_C51STARTUP ----- ----- +--> ?PR?MAIN?MAIN ?PR?MAIN?MAIN 0008H 0004H +--> ?PR?FUNC_1?MAIN ?PR?FUNC_1?MAIN 000CH 0010H +--> ?PR?FUNC_2?MAIN ?PR?FUNC_2?MAIN 001CH 0014H
SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?PR?MAIN?MAIN 0008H 0004H +--> ?PR?FUNC_1?MAIN
SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?PR?FUNC_1?MAIN 000CH 0010H +--> ?PR?FUNC_2?MAIN
SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?PR?FUNC_2?MAIN 001CH 0014H
SEGMENT DATA_GROUP +--> CALLED SEGMENT START LENGTH ---------------------------------------------- ?C_C51STARTUP ----- ----- ?PR?MAIN?MAIN 0008H 0004H ?PR?FUNC_1?MAIN 000CH 0010H ?PR?FUNC_2?MAIN 001CH 0014H
If only I could get the list you show. My results (with 6.01) is a long list of functions with ONLY the first having numbers associated with it. My perception is that these are the functions using the same space to store variables. HOWEVER, these functions use a varied number of variables and the length shown is for the one(s) using the most. What I show in the example some postings back is what I get.
OK - E-mail me the MAP file (jonw@keil.com). I'll take a look at it. However, I don't recall any problems with the 6.01 version of the tools generating this tree incorrectly. Jon