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