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