26b52112b2716cd4e815b75b3e68b4559f481ee6
[fw/sdcc] / src / xa51 / main.c
1 /* @file main.c
2    xa51 specific general functions.
3 */
4
5 #include "common.h"
6 #include "main.h"
7 #include "ralloc.h"
8 #include "gen.h"
9
10 static char _defaultRules[] =
11 {
12 #include "peeph.rul"
13 };
14
15 /* list of key words used by xa51 */
16 static char *_xa51_keywords[] =
17 {
18   "at",
19   "bit",
20   "code",
21   "critical",
22   "data",
23   "far",
24   //"idata",
25   "interrupt",
26   "near",
27   //"pdata",
28   "reentrant",
29   "sfr",
30   "sbit",
31   "using",
32   "xdata",
33   //"_data",
34   //"_code",
35   //"_generic",
36   //"_near",
37   //"_xdata",
38   //"_pdata",
39   //"_idata",
40   "_naked",
41   //"_overlay",
42   NULL
43 };
44
45 /* rewinds declared in asm.c, function printCLine().
46  * Currently commented out.
47  *
48  * extern int rewinds;
49  */
50 void   _xa51_genAssemblerEnd (FILE * of)
51 {
52   //fprintf (stderr, "Did %d rewind%c for c-line in asm comments\n", rewinds,
53   //rewinds==1 ? '\0' : 's');
54 }
55
56 void xa51_assignRegisters (eBBlock ** ebbs, int count);
57
58 static int regParmFlg = 0;      /* determine if we can register a parameter */
59
60 static void
61 _xa51_init (void)
62 {
63   asm_addTree (&asm_xa_asm_mapping);
64 }
65
66 static void
67 _xa51_reset_regparm ()
68 {
69   regParmFlg = 0;
70 }
71
72 static int
73 _xa51_regparm (sym_link * l)
74 {
75   return 0; // for now
76   /* for this processor it is simple
77      can pass only the first parameter in a register */
78   if (regParmFlg)
79     return 0;
80
81   regParmFlg = 1;
82   return 1;
83 }
84
85 static bool
86 _xa51_parseOptions (int *pargc, char **argv, int *i)
87 {
88   /* TODO: allow port-specific command line options to specify
89    * segment names here.
90    */
91   return FALSE;
92 }
93
94 static void
95 _xa51_finaliseOptions (void)
96 {
97   fprintf (stderr, "*** WARNING *** The XA51 port isn't yet complete\n");
98   port->mem.default_local_map = istack;
99   port->mem.default_globl_map = xdata;
100   if (options.model!=MODEL_PAGE0) {
101     fprintf (stderr, "-mxa51 only supports --model-page0\n");
102     exit (1);
103   }
104 }
105
106 static void
107 _xa51_setDefaultOptions (void)
108 {
109   options.stackAuto=1;
110   options.intlong_rent=1;
111   options.float_rent=1;
112   options.stack_loc=0x100;
113   options.data_loc=0;
114 }
115
116 static const char *
117 _xa51_getRegName (struct regs *reg)
118 {
119   if (reg)
120     return reg->name;
121   return "err";
122 }
123
124 /* Generate interrupt vector table. */
125 static int
126 _xa51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
127 {
128   return TRUE;
129 }
130
131 /* Generate code to copy XINIT to XISEG */
132 static void _xa51_genXINIT (FILE * of) {
133   fprintf (of, ";       _xa51_genXINIT() start\n");
134   fprintf (of, "        mov     r0,#l_XINIT\n");
135   fprintf (of, "        beq     00002$\n");
136   fprintf (of, "        mov     r1,#s_XINIT\n");
137   fprintf (of, "        mov     r2,#s_XISEG\n");
138   fprintf (of, "00001$: movc    r3l,[r1+]\n");
139   fprintf (of, "        mov     [r2+],r3l\n");
140   fprintf (of, "        djnz    r0,00001$\n");
141   fprintf (of, "00002$:\n");
142   fprintf (of, ";       _xa51_genXINIT() end\n");
143 }
144
145 static void
146 _xa51_genAssemblerPreamble (FILE * of)
147 {
148   symbol *mainExists=newSymbol("main", 0);
149   mainExists->block=0;
150
151   if ((mainExists=findSymWithLevel(SymbolTab, mainExists))) {
152     fprintf (of, "\t.area GSINIT\t(CODE)\n");
153     fprintf (of, "__interrupt_vect:\n");
154     fprintf (of, "\t.dw\t0x8f00\n");
155     fprintf (of, "\t.dw\t__sdcc_gsinit_startup\n");
156     fprintf (of, "\n");
157     fprintf (of, "__sdcc_gsinit_startup:\n");
158     fprintf (of, ";\tmov.b\t_SCR,#0x01\t; page zero mode\n");
159     fprintf (of, "\t.db 0x96,0x48,0x40,0x01\n");
160     fprintf (of, "\tmov\tr7,#0x%04x\n", options.stack_loc);
161     fprintf (of, "\tcall\t_external_startup\n");
162     _xa51_genXINIT(of);
163     fprintf (of, "\t.area CSEG\t(CODE)\n");
164     fprintf (of, "\tcall\t_main\n");
165     fprintf (of, "\treset\t;main should not return\n");
166   }
167 }
168
169 /* dummy linker for now */
170 void xa_link(void) {
171 }
172
173 /* Do CSE estimation */
174 static bool cseCostEstimation (iCode *ic, iCode *pdic)
175 {
176     operand *result = IC_RESULT(ic);
177     sym_link *result_type = operandType(result);
178
179     /* if it is a pointer then return ok for now */
180     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
181     
182     /* if bitwise | add & subtract then no since xa51 is pretty good at it 
183        so we will cse only if they are local (i.e. both ic & pdic belong to
184        the same basic block */
185     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
186         /* then if they are the same Basic block then ok */
187         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
188         else return 0;
189     }
190         
191     /* for others it is cheaper to do the cse */
192     return 1;
193 }
194
195 /* Indicate which extended bit operations this port supports */
196 static bool
197 hasExtBitOp (int op, int size)
198 {
199   if (op == RRC
200       || op == RLC
201       || op == GETHBIT
202      )
203     return TRUE;
204   else
205     return FALSE;
206 }
207
208 /* Indicate the expense of an access to an output storage class */
209 static int
210 oclsExpense (struct memmap *oclass)
211 {
212   if (IN_FARSPACE(oclass))
213     return 1;
214     
215   return 0;
216 }
217
218
219 /** $1 is always the basename.
220     $2 is always the output file.
221     $3 varies
222     $l is the list of extra options that should be there somewhere...
223     MUST be terminated with a NULL.
224 */
225 static const char *_linkCmd[] =
226 {
227   "xa_link", "", "\"$1\"", NULL
228 };
229
230 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
231 static const char *_asmCmd[] =
232 {
233   "xa_rasm", "$l", "$3", "\"$1.asm\"", NULL
234 };
235
236 /* Globals */
237 PORT xa51_port =
238 {
239   TARGET_ID_XA51,
240   "xa51",
241   "MCU 80C51XA",                /* Target name */
242   NULL,                         /* Processor name */
243   {
244     glue,
245     FALSE,                      /* Emit glue around main */
246     MODEL_PAGE0,
247     MODEL_PAGE0
248   },
249   {
250     _asmCmd,
251     NULL,
252     "",                         /* Options with debug */
253     "",                         /* Options without debug */
254     0,
255     ".asm",
256     NULL                        /* no do_assemble function */
257   },
258   {
259     _linkCmd,
260     NULL,
261     NULL,
262     ".rel",
263     1
264   },
265   {
266     _defaultRules
267   },
268   {
269         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
270     1, 2, 2, 4, 2, 2, 3, 1, 4, 4
271   },
272   {
273     "XSEG    (XDATA)",
274     "STACK   (XDATA)",
275     "CSEG    (CODE)",
276     "DSEG    (DATA)",
277     NULL, //"ISEG    (DATA)",
278     "XSEG    (XDATA)",
279     "BSEG    (BIT)",
280     NULL, //"RSEG    (DATA)",
281     "GSINIT  (CODE)",
282     NULL, //"OSEG    (OVR,XDATA)",
283     "GSFINAL (CODE)",
284     "HOME    (CODE)",
285     "XISEG   (XDATA)", // initialized xdata
286     "XINIT   (CODE)", // a code copy of xiseg
287     NULL, // default local map
288     NULL, // default global map
289     1
290   },
291   { NULL, NULL },
292   {
293     -1, // stack grows down
294     0, // bank overhead NUY
295     4, // isr overhead, page zero mode
296     2, // function call overhead, page zero mode
297     0, // reentrant overhead NUY
298     0 // banked overhead NUY
299   },
300     /* xa51 has an 16 bit mul */
301   {
302     2, -2
303   },
304   {
305     xa51_emitDebuggerSymbol
306   },
307   {
308     255/3,      /* maxCount */
309     3,          /* sizeofElement */
310     /* The rest of these costs are bogus. They approximate */
311     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
312     {4,4,4},    /* sizeofMatchJump[] */
313     {0,0,0},    /* sizeofRangeCompare[] */
314     0,          /* sizeofSubtract */
315     3,          /* sizeofDispatch */
316   },
317   "_",
318   _xa51_init,
319   _xa51_parseOptions,
320   NULL,
321   NULL,
322   _xa51_finaliseOptions,
323   _xa51_setDefaultOptions,
324   xa51_assignRegisters,
325   _xa51_getRegName,
326   _xa51_keywords,
327   _xa51_genAssemblerPreamble,
328   _xa51_genAssemblerEnd,
329   _xa51_genIVT,
330   _xa51_genXINIT,
331   NULL,                         /* genInitStartup */
332   _xa51_reset_regparm,
333   _xa51_regparm,
334   NULL, // process_pragma()
335   NULL, // getMangledFunctionName()
336   NULL, // hasNativeMulFor()
337   hasExtBitOp,                  /* hasExtBitOp */
338   oclsExpense,                  /* oclsExpense */
339   TRUE, // use_dw_for_init
340   TRUE,                         /* little endian */
341   0,                            /* leave lt */
342   0,                            /* leave gt */
343   1,                            /* transform <= to ! > */
344   1,                            /* transform >= to ! < */
345   1,                            /* transform != to !(a == b) */
346   0,                            /* leave == */
347   FALSE,                        /* No array initializer support. */
348   cseCostEstimation,
349   NULL,                         /* no builtin functions */
350   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
351   1,                            /* reset labelKey to 1 */
352   1,                            /* globals & local static allowed */
353   PORT_MAGIC
354 };