fix several 'three operand in far space' problems
[fw/sdcc] / doc / SDCCUdoc-25.html
index 7809e0177580536a4003521b4a6acc5706abf02f..c42b795f8f7bf828defcdb8c56615164b372acde 100644 (file)
@@ -1,8 +1,8 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 <HTML>
 <HEAD>
- <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
- <TITLE>SDCC Compiler User Guide: Retargetting for other MCUs.</TITLE>
+ <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.7">
+ <TITLE>SDCC Compiler User Guide: TIPS</TITLE>
  <LINK HREF="SDCCUdoc-26.html" REL=next>
  <LINK HREF="SDCCUdoc-24.html" REL=previous>
  <LINK HREF="SDCCUdoc.html#toc25" REL=contents>
 <A HREF="SDCCUdoc-24.html">Previous</A>
 <A HREF="SDCCUdoc.html#toc25">Contents</A>
 <HR>
-<H2><A NAME="Retargetting"></A> <A NAME="s25">25. Retargetting for other MCUs.</A> </H2>
+<H2><A NAME="Tips"></A> <A NAME="s25">25. TIPS</A> </H2>
 
-<P>The issues for retargetting the compiler are far too numerous to be covered
-by this document. What follows is a brief description of each of the seven
-phases of the compiler and its MCU dependency.
+<P>Here are a few guide-lines that will help the compiler generate more efficient
+code, some of the tips are specific to this compiler others are generally good
+programming practice.
 <P>
-<OL>
-<LI>Parsing the source and building the annotated parse tree. This phase is
-largely MCU independent (except for the language extensions). Syntax &amp;
-semantic checks are also done in this phase , along with some initial optimizations
-like back patching labels and the pattern matching optimizations like bit-rotation
-etc.</LI>
-<LI>The second phase involves generating an intermediate code which can be
-easy manipulated during the later phases. This phase is entirely MCU independent.
-The intermediate code generation assumes the target machine has unlimited number
-of registers, and designates them with the name iTemp. The compiler can be
-made to dump a human readable form of the code generated by using the --dumpraw
-option.</LI>
-<LI>This phase does the bulk of the standard optimizations and is also MCU
-independent. This phase can be broken down into several sub-phases.
 <UL>
-<LI>Break down intermediate code (iCode) into basic blocks.</LI>
-<LI>Do control flow &amp; data flow analysis on the basic blocks.</LI>
-<LI>Do local common subexpression elimination, then global subexpression elimination</LI>
-<LI>dead code elimination</LI>
-<LI>loop optimizations</LI>
-<LI>if loop optimizations caused any changes then do 'global subexpression
-elimination' and 'dead code elimination' again.</LI>
-</UL>
-</LI>
-<LI>This phase determines the live-ranges; by live range I mean those iTemp
-variables defined by the compiler that still survive after all the optimizations.
-Live range analysis is essential for register allocation, since these computation
-determines which of these iTemps will be assigned to registers, and for how
-long.</LI>
-<LI>Phase five is register allocation. There are two parts to this process
-.
-<OL>
-<LI>The first part I call 'register packing' (for lack of a better term) .
-In this case several MCU specific expression folding is done to reduce register
-pressure.</LI>
-<LI>The second part is more MCU independent and deals with allocating registers
-to the remaining live ranges. A lot of MCU specific code does creep into this
-phase because of the limited number of index registers available in the 8051.</LI>
-</OL>
+<LI>Use the smallest data type to represent your data-value. If it is known
+in advance that the value is going to be less than 256 then use a 'short' or
+'char' instead of an 'int'.</LI>
+<LI>Use unsigned when it is known in advance that the value is not going to
+be negative. This helps especially if you are doing division or multiplication.</LI>
+<LI>NEVER jump into a LOOP.</LI>
+<LI>Declare the variables to be local whenever possible, especially loop control
+variables (induction).</LI>
+<LI>Since the compiler does not do implicit integral promotion, the programmer
+should do an explicit cast when integral promotion is required.</LI>
+<LI>Reducing the size of division , multiplication &amp; modulus operations
+can reduce code size substantially. Take the following code for example.
+<PRE>
+foobar( unsigned int p1, unsigned char ch)
+{
+    unsigned char ch1
+ = p1 % ch ;
+    ....    
+}
+  
+</PRE>
+
+<P>For the modulus operation the variable ch will be promoted to unsigned
+int first then the modulus operation will be performed (this will lead to a
+call to a support routine). If the code is changed to 
+
+<P>
+<PRE>
+foobar( unsigned int p1, unsigned char ch)
+{
+    unsigned char ch1
+ = (unsigned char)p1 % ch ;
+    ....    
+}
+  
+</PRE>
+<P>It would substantially reduce the code generated (future versions of the
+compiler will be smart enough to detect such optimization oppurtunities).
 </LI>
-<LI>The Code generation phase is (unhappily), entirely MCU dependent and very
-little (if any at all) of this code can be reused for other MCU. However the
-scheme for allocating a homogenized assembler operand for each iCode operand
-may be reused.</LI>
-<LI>As mentioned in the optimization section the peep-hole optimizer is rule
-based system, which can reprogrammed for other MCUs.</LI>
-</OL>
+</UL>
+<P><B>Notes from an USER ( Trefor@magera.freeserve.co.uk )</B>
+<P>The 8051 family of micro controller have a minimum of 128 bytes of internal
+memory which is structured as follows
+<P>- Bytes 00-1F - 32 bytes to hold up to 4 banks of the registers R7 to R7
+<P>
+<P>- Bytes 20-2F - 16 bytes to hold 128 bit variables and 
+<P>- Bytes 30-7F - 60 bytes for general purpose use.
+<P>Normally the SDCC compiler will only utilise the first bank of registers,
+but it is possible to specify that other banks of registers should be used
+in interrupt routines. By default, the compiler will place the stack after
+the last bank of used registers, i.e. if the first 2 banks of registers are
+used, it will position the base of the internal stack at address 16 (0X10).
+This implies that as the stack grows, it will use up the remaining register
+banks, and the 16 bytes used by the 128 bit variables, and 60 bytes for general
+purpose use.
+<P>By default, the compiler uses the 60 general purpose bytes to hold &quot;near
+data&quot;. The compiler/optimiser may also declare some Local Variables in
+this area to hold local data. 
+<P>If any of the 128 bit variables are used, or near data is being used then
+care needs to be taken to ensure that the stack does not grow so much that
+it starts to over write either your bit variables or &quot;near data&quot;.
+There is no runtime checking to prevent this from happening.
+<P>The amount of stack being used is affected by the use of the &quot;internal
+stack&quot; to save registers before a subroutine call is made, - --stack-auto
+will declare parameters and local variables on the stack - the number of nested
+subroutines.
+<P>If you detect that the stack is over writing you data, then the following
+can be done. --xstack will cause an external stack to be used for saving registers
+and (if --stack-auto is being used) storing parameters and local variables.
+However this will produce more and code which will be slower to execute. 
+<P>--stack-loc will allow you specify the start of the stack, i.e. you could
+start it after any data in the general purpose area. However this may waste
+the memory not used by the register banks and if the size of the &quot;near
+data&quot; increases, it may creep into the bottom of the stack.
+<P>--stack-after-data, similar to the --stack-loc, but it automatically places
+the stack after the end of the &quot;near data&quot;. Again this could waste
+any spare register space.
+<P>--data-loc allows you to specify the start address of the near data. This
+could be used to move the &quot;near data&quot; further away from the stack
+giving it more room to grow. This will only work if no bit variables are being
+used and the stack can grow to use the bit variable space.
+<P>Conclusion.
+<P>If you find that the stack is over writing your bit variables or &quot;near
+data&quot; then the approach which best utilised the internal memory is to
+position the &quot;near data&quot; after the last bank of used registers
+or, if you use bit variables, after the last bit variable by using the --data-loc,
+e.g. if two register banks are being used and no data variables, --data-loc
+16, and - use the --stack-after-data option.
+<P>If bit variables are being used, another method would be to try and squeeze
+the data area in the unused register banks if it will fit, and start the stack
+after the last bit variable.
 <HR>
 <A HREF="SDCCUdoc-26.html">Next</A>
 <A HREF="SDCCUdoc-24.html">Previous</A>