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