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