Changed stack usage declaration to match sdcc/src/mcs51/gen.c:1.121+. This fixes...
[fw/sdcc] / src / mcs51 / main.c
1 /** @file main.c
2     mcs51 specific general functions.
3
4     Note that mlh prepended _mcs51_ on the static functions.  Makes
5     it easier to set a breakpoint using the debugger.
6 */
7 #include "common.h"
8 #include "main.h"
9 #include "ralloc.h"
10 #include "gen.h"
11 #include "../SDCCutil.h"
12 extern const char *preArgv[128];        /* pre-processor arguments  */
13
14 static char _defaultRules[] =
15 {
16 #include "peeph.rul"
17 };
18
19 /* list of key words used by msc51 */
20 static char *_mcs51_keywords[] =
21 {
22   "at",
23   "bit",
24   "code",
25   "critical",
26   "data",
27   "far",
28   "idata",
29   "interrupt",
30   "near",
31   "pdata",
32   "reentrant",
33   "sfr",
34   "sbit",
35   "using",
36   "xdata",
37   "_data",
38   "_code",
39   "_generic",
40   "_near",
41   "_xdata",
42   "_pdata",
43   "_idata",
44   "_naked",
45   "_overlay",
46   NULL
47 };
48
49
50 void mcs51_assignRegisters (eBBlock ** ebbs, int count);
51
52 static int regParmFlg = 0;      /* determine if we can register a parameter */
53
54 static void
55 _mcs51_init (void)
56 {
57   asm_addTree (&asm_asxxxx_mapping);
58 }
59
60 static void
61 _mcs51_reset_regparm ()
62 {
63   regParmFlg = 0;
64 }
65
66 static int
67 _mcs51_regparm (sym_link * l)
68 {
69     if (options.parms_in_bank1 == 0) {
70         /* simple can pass only the first parameter in a register */
71         if (regParmFlg)
72             return 0;
73
74         regParmFlg = 1;
75         return 1;
76     } else {
77         int size = getSize(l);
78         int remain ;
79
80         /* first one goes the usual way to DPTR */
81         if (regParmFlg == 0) {
82             regParmFlg += 4 ;
83             return 1;
84         }
85         /* second one onwards goes to RB1_0 thru RB1_7 */
86         remain = regParmFlg - 4;
87         if (size > (8 - remain)) {
88             regParmFlg = 12 ;
89             return 0;
90         }
91         regParmFlg += size ;
92         return regParmFlg - size + 1;   
93     }
94 }
95
96 static bool
97 _mcs51_parseOptions (int *pargc, char **argv, int *i)
98 {
99   /* TODO: allow port-specific command line options to specify
100    * segment names here.
101    */
102   return FALSE;
103 }
104
105 static void
106 _mcs51_finaliseOptions (void)
107 {
108   if (noXinitOpt /* || options.model==MODEL_SMALL */) {
109     port->genXINIT=0;
110   }
111
112   if (options.model == MODEL_LARGE) {
113       port->mem.default_local_map = xdata;
114       port->mem.default_globl_map = xdata;
115     }
116   else
117     {
118       port->mem.default_local_map = data;
119       port->mem.default_globl_map = data;
120     }
121
122   if (options.parms_in_bank1) {
123       addToList (preArgv, "-DSDCC_PARMS_IN_BANK1");
124   }
125 }
126
127 static void
128 _mcs51_setDefaultOptions (void)
129 {
130 }
131
132 static const char *
133 _mcs51_getRegName (struct regs *reg)
134 {
135   if (reg)
136     return reg->name;
137   return "err";
138 }
139
140 static void
141 _mcs51_genAssemblerPreamble (FILE * of)
142 {
143     if (options.parms_in_bank1) {
144         int i ;
145         for (i=0; i < 8 ; i++ )
146             fprintf (of,"b1_%d = 0x%x \n",i,8+i);
147     }
148 }
149
150 /* Generate interrupt vector table. */
151 static int
152 _mcs51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
153 {
154   return FALSE;
155 }
156
157 /* Generate code to copy XINIT to XISEG */
158 static void _mcs51_genXINIT (FILE * of) {
159   fprintf (of, ";       _mcs51_genXINIT() start\n");
160   fprintf (of, "        mov     a,#l_XINIT\n");
161   fprintf (of, "        orl     a,#l_XINIT>>8\n");
162   fprintf (of, "        jz      00003$\n");
163   fprintf (of, "        mov     a,#s_XINIT\n");
164   fprintf (of, "        add     a,#l_XINIT\n");
165   fprintf (of, "        mov     r1,a\n");
166   fprintf (of, "        mov     a,#s_XINIT>>8\n");
167   fprintf (of, "        addc    a,#l_XINIT>>8\n");
168   fprintf (of, "        mov     r2,a\n");
169   fprintf (of, "        mov     dptr,#s_XINIT\n");
170   fprintf (of, "        mov     r0,#s_XISEG\n");
171   fprintf (of, "        mov     p2,#(s_XISEG >> 8)\n");
172   fprintf (of, "00001$: clr     a\n");
173   fprintf (of, "        movc    a,@a+dptr\n");
174   fprintf (of, "        movx    @r0,a\n");
175   fprintf (of, "        inc     dptr\n");
176   fprintf (of, "        inc     r0\n");
177   fprintf (of, "        cjne    r0,#0,00002$\n");
178   fprintf (of, "        inc     p2\n");
179   fprintf (of, "00002$: mov     a,dpl\n");
180   fprintf (of, "        cjne    a,ar1,00001$\n");
181   fprintf (of, "        mov     a,dph\n");
182   fprintf (of, "        cjne    a,ar2,00001$\n");
183   fprintf (of, "        mov     p2,#0xFF\n");
184   fprintf (of, "00003$:\n");
185   fprintf (of, ";       _mcs51_genXINIT() end\n");
186 }
187
188
189 /* Do CSE estimation */
190 static bool cseCostEstimation (iCode *ic, iCode *pdic)
191 {
192     operand *result = IC_RESULT(ic);
193     sym_link *result_type = operandType(result);
194
195     /* if it is a pointer then return ok for now */
196     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
197     
198     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
199        so we will cse only if they are local (i.e. both ic & pdic belong to
200        the same basic block */
201     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
202         /* then if they are the same Basic block then ok */
203         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
204         else return 0;
205     }
206         
207     /* for others it is cheaper to do the cse */
208     return 1;
209 }
210
211 /** $1 is always the basename.
212     $2 is always the output file.
213     $3 varies
214     $l is the list of extra options that should be there somewhere...
215     MUST be terminated with a NULL.
216 */
217 static const char *_linkCmd[] =
218 {
219   "aslink", "-nf", "$1", NULL
220 };
221
222 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
223 static const char *_asmCmd[] =
224 {
225   "asx8051", "$l", "$3", "$1.asm", NULL
226 };
227
228 /* Globals */
229 PORT mcs51_port =
230 {
231   TARGET_ID_MCS51,
232   "mcs51",
233   "MCU 8051",                   /* Target name */
234   NULL,                         /* Processor name */
235   {
236     TRUE,                       /* Emit glue around main */
237     MODEL_SMALL | MODEL_LARGE,
238     MODEL_SMALL
239   },
240   {
241     _asmCmd,
242     NULL,
243     "-plosgffc",                /* Options with debug */
244     "-plosgff",                 /* Options without debug */
245     0,
246     ".asm",
247     NULL                        /* no do_assemble function */
248   },
249   {
250     _linkCmd,
251     NULL,
252     NULL,
253     ".rel"
254   },
255   {
256     _defaultRules
257   },
258   {
259         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
260     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
261   },
262   {
263     "XSEG    (XDATA)",
264     "STACK   (DATA)",
265     "CSEG    (CODE)",
266     "DSEG    (DATA)",
267     "ISEG    (DATA)",
268     "XSEG    (XDATA)",
269     "BSEG    (BIT)",
270     "RSEG    (DATA)",
271     "GSINIT  (CODE)",
272     "OSEG    (OVR,DATA)",
273     "GSFINAL (CODE)",
274     "HOME    (CODE)",
275     "XISEG   (XDATA)", // initialized xdata
276     "XINIT   (CODE)", // a code copy of xiseg
277     NULL,
278     NULL,
279     1
280   },
281   {
282     +1, 0, 4, 1, 1, 0
283   },
284     /* mcs51 has an 8 bit mul */
285   {
286     1, -1
287   },
288   "_",
289   _mcs51_init,
290   _mcs51_parseOptions,
291   NULL,
292   _mcs51_finaliseOptions,
293   _mcs51_setDefaultOptions,
294   mcs51_assignRegisters,
295   _mcs51_getRegName,
296   _mcs51_keywords,
297   _mcs51_genAssemblerPreamble,
298   NULL,                         /* no genAssemblerEnd */
299   _mcs51_genIVT,
300   _mcs51_genXINIT,
301   _mcs51_reset_regparm,
302   _mcs51_regparm,
303   NULL,
304   NULL,
305   NULL,
306   FALSE,
307   0,                            /* leave lt */
308   0,                            /* leave gt */
309   1,                            /* transform <= to ! > */
310   1,                            /* transform >= to ! < */
311   1,                            /* transform != to !(a == b) */
312   0,                            /* leave == */
313   FALSE,                        /* No array initializer support. */
314   cseCostEstimation,
315   NULL,                         /* no builtin functions */
316   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
317   1,                            /* reset labelKey to 1 */
318   1,                            /* globals & local static allowed */
319   PORT_MAGIC
320 };