Imported Upstream version 2.9.0
[debian/cc1111] / 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 SDCCasm.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 (ebbIndex *);
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 (void)
68 {
69   regParmFlg = 0;
70 }
71
72 static int
73 _xa51_regparm (sym_link * l, bool reentrant)
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 (struct dbuf_s * oBuf, 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   /* tags for generic pointers */
273   { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
274   {
275     "XSEG    (XDATA)",
276     "STACK   (XDATA)",
277     "CSEG    (CODE)",
278     "DSEG    (DATA)",
279     NULL, //"ISEG    (DATA)",
280     NULL, //"PSEG    (PAG,XDATA)",
281     "XSEG    (XDATA)",
282     "BSEG    (BIT)",
283     NULL, //"RSEG    (DATA)",
284     "GSINIT  (CODE)",
285     NULL, //"OSEG    (OVR,XDATA)",
286     "GSFINAL (CODE)",
287     "HOME    (CODE)",
288     "XISEG   (XDATA)", // initialized xdata
289     "XINIT   (CODE)", // a code copy of xiseg
290     "CONST   (CODE)",           // const_name - const data (code or not)
291     "CABS    (ABS,CODE)",       // cabs_name - const absolute data (code or not)
292     "XABS    (ABS,XDATA)",      // xabs_name - absolute xdata
293     "IABS    (ABS,DATA)",       // iabs_name - absolute data
294     NULL, // default local map
295     NULL, // default global map
296     1
297   },
298   { NULL, NULL },
299   {
300     -1, // stack grows down
301     0, // bank overhead NUY
302     4, // isr overhead, page zero mode
303     2, // function call overhead, page zero mode
304     0, // reentrant overhead NUY
305     0 // banked overhead NUY
306   },
307     /* xa51 has an 16 bit mul */
308   {
309     2, -2
310   },
311   {
312     xa51_emitDebuggerSymbol
313   },
314   {
315     255/3,      /* maxCount */
316     3,          /* sizeofElement */
317     /* The rest of these costs are bogus. They approximate */
318     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
319     {4,4,4},    /* sizeofMatchJump[] */
320     {0,0,0},    /* sizeofRangeCompare[] */
321     0,          /* sizeofSubtract */
322     3,          /* sizeofDispatch */
323   },
324   "_",
325   _xa51_init,
326   _xa51_parseOptions,
327   NULL,
328   NULL,
329   _xa51_finaliseOptions,
330   _xa51_setDefaultOptions,
331   xa51_assignRegisters,
332   _xa51_getRegName,
333   _xa51_keywords,
334   _xa51_genAssemblerPreamble,
335   _xa51_genAssemblerEnd,
336   _xa51_genIVT,
337   _xa51_genXINIT,
338   NULL,                         /* genInitStartup */
339   _xa51_reset_regparm,
340   _xa51_regparm,
341   NULL, // process_pragma()
342   NULL, // getMangledFunctionName()
343   NULL, // hasNativeMulFor()
344   hasExtBitOp,                  /* hasExtBitOp */
345   oclsExpense,                  /* oclsExpense */
346   TRUE, // use_dw_for_init
347   TRUE,                         /* little endian */
348   0,                            /* leave lt */
349   0,                            /* leave gt */
350   1,                            /* transform <= to ! > */
351   1,                            /* transform >= to ! < */
352   1,                            /* transform != to !(a == b) */
353   0,                            /* leave == */
354   FALSE,                        /* No array initializer support. */
355   cseCostEstimation,
356   NULL,                         /* no builtin functions */
357   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
358   1,                            /* reset labelKey to 1 */
359   1,                            /* globals & local static allowed */
360   PORT_MAGIC
361 };