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