(_ds390_genXINIT) added test for 0 length
[fw/sdcc] / src / ds390 / main.c
1 /** @file main.c
2     ds390 specific general functions.
3
4     Note that mlh prepended _ds390_ 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 *_ds390_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   NULL
44 };
45
46 static builtins __ds390_builtins[] = {
47     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
48     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
49     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
50     { NULL , NULL,0, {NULL}}                       /* mark end of table */
51 };    
52 void ds390_assignRegisters (eBBlock ** ebbs, int count);
53
54 static int regParmFlg = 0;      /* determine if we can register a parameter */
55
56 static void
57 _ds390_init (void)
58 {
59   asm_addTree (&asm_asxxxx_mapping);
60 }
61
62 static void
63 _ds390_reset_regparm ()
64 {
65   regParmFlg = 0;
66 }
67
68 static int
69 _ds390_regparm (sym_link * l)
70 {
71   /* for this processor it is simple
72      can pass only the first parameter in a register */
73   if (regParmFlg)
74     return 0;
75
76   regParmFlg = 1;
77   return 1;
78 }
79
80 static bool
81 _ds390_parseOptions (int *pargc, char **argv, int *i)
82 {
83   /* TODO: allow port-specific command line options to specify
84    * segment names here.
85    */
86   return FALSE;
87 }
88
89 static void
90 _ds390_finaliseOptions (void)
91 {
92   /* Hack-o-matic: if we are using the flat24 model,
93    * adjust pointer sizes.
94    */
95   if (options.model != MODEL_FLAT24)  {
96       fprintf (stderr,
97                "*** warning: ds390 port small and large model experimental.\n");
98       if (options.model == MODEL_LARGE)
99       {
100         port->mem.default_local_map = xdata;
101         port->mem.default_globl_map = xdata;
102       }
103       else
104       {
105         port->mem.default_local_map = data;
106         port->mem.default_globl_map = data;
107       }
108   }
109   else {
110     port->s.fptr_size = 3;
111     port->s.gptr_size = 4;
112
113     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
114
115     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
116                                  * of return addres on the stack.
117                                  * but is ugly. There must be a 
118                                  * better way.
119                                  */
120
121     port->mem.default_local_map = xdata;
122     port->mem.default_globl_map = xdata;
123
124     if (!options.stack10bit)
125     {
126     fprintf (stderr,
127              "*** error: ds390 port only supports the 10 bit stack mode.\n");
128     } else {
129         if (!options.stack_loc) options.stack_loc = 0x400007;
130     }
131     
132     /* generate native code 16*16 mul/div */
133     if (options.useAccelerator) 
134             port->support.muldiv=2;
135     else 
136             port->support.muldiv=1;
137
138      /* Fixup the memory map for the stack; it is now in
139      * far space and requires a FPOINTER to access it.
140      */
141     istack->fmap = 1;
142     istack->ptrType = FPOINTER;
143   }  /* MODEL_FLAT24 */
144 }
145
146 static void
147 _ds390_setDefaultOptions (void)
148 {
149   options.model=MODEL_FLAT24;
150   options.stack10bit=1;
151 }
152
153 static const char *
154 _ds390_getRegName (struct regs *reg)
155 {
156   if (reg)
157     return reg->name;
158   return "err";
159 }
160
161 static void
162 _ds390_genAssemblerPreamble (FILE * of)
163 {
164       if (options.model == MODEL_FLAT24)
165         fputs (".flat24 on\t\t; 24 bit flat addressing\n", of);
166
167       fputs ("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
168       fputs ("dps = 0x86\t\t; dps register unknown to assembler\n", of);
169       fputs ("dpl1 = 0x84\t\t; dpl1 register unknown to assembler\n", of);
170       fputs ("dph1 = 0x85\t\t; dph1 register unknown to assembler\n", of);
171       fputs ("dpx1 = 0x95\t\t; dpx1 register unknown to assembler\n", of);
172       fputs ("ap = 0x9C\t\t; ap register unknown to assembler\n", of);
173       fputs ("mcnt0 = 0xD1\t\t; mcnt0 register unknown to assembler\n", of);
174       fputs ("mcnt1 = 0xD2\t\t; mcnt1 register unknown to assembler\n", of);
175       fputs ("ma = 0xD3\t\t; ma register unknown to assembler\n", of);
176       fputs ("mb = 0xD4\t\t; mb register unknown to assembler\n", of);
177       fputs ("mc = 0xD5\t\t; mc register unknown to assembler\n", of);
178       fputs ("F1 = 0xD1\t\t; F1 user flag unknown to assembler\n", of);
179       fputs ("esp = 0x9B\t\t; ESP user flag unknown to assembler\n", of);
180 }
181
182 /* Generate interrupt vector table. */
183 static int
184 _ds390_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
185 {
186   int i;
187
188   if (options.model != MODEL_FLAT24)
189     {
190       /* Let the default code handle it. */
191       return FALSE;
192     }
193
194   fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
195
196   /* now for the other interrupts */
197   for (i = 0; i < maxInterrupts; i++)
198     {
199       if (interrupts[i])
200         {
201           fprintf (of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
202         }
203       else
204         {
205           fprintf (of, "\treti\n\t.ds\t7\n");
206         }
207     }
208
209   return TRUE;
210 }
211
212 /* Generate code to copy XINIT to XISEG */
213 static void _ds390_genXINIT (FILE * of) {
214   fprintf (of, ";       _ds390_genXINIT() start\n");
215   fprintf (of, "        mov     a,#l_XINIT\n");
216   fprintf (of, "        add     a,#l_XINIT>>8\n");
217   fprintf (of, "        jz      00003$\n");
218   fprintf (of, "        mov     a,#s_XINIT\n");
219   fprintf (of, "        add     a,#l_XINIT\n");
220   fprintf (of, "        mov     r1,a\n");
221   fprintf (of, "        mov     a,#s_XINIT>>8\n");
222   fprintf (of, "        addc    a,#l_XINIT>>8\n");
223   fprintf (of, "        mov     r2,a\n");
224   fprintf (of, "        mov     dptr,#s_XINIT\n");
225   fprintf (of, "        mov     dps,#0x21\n");
226   fprintf (of, "        mov     dptr,#s_XISEG\n");
227   fprintf (of, "00001$: clr     a\n");
228   fprintf (of, "        movc    a,@a+dptr\n");
229   fprintf (of, "        movx    @dptr,a\n");
230   fprintf (of, "        inc     dptr\n");
231   fprintf (of, "        inc     dptr\n");
232   fprintf (of, "00002$: mov     a,dpl\n");
233   fprintf (of, "        cjne    a,ar1,00001$\n");
234   fprintf (of, "        mov     a,dph\n");
235   fprintf (of, "        cjne    a,ar2,00001$\n");
236   fprintf (of, "        mov     dps,#0\n");
237   fprintf (of, "00003$:\n");
238   fprintf (of, ";       _ds390_genXINIT() end\n");
239 }
240
241 /* Do CSE estimation */
242 static bool cseCostEstimation (iCode *ic, iCode *pdic)
243 {
244     operand *result = IC_RESULT(ic);
245     //operand *right  = IC_RIGHT(ic);
246     //operand *left   = IC_LEFT(ic);
247     sym_link *result_type = operandType(result);
248     //sym_link *right_type  = (right ? operandType(right) : 0);
249     //sym_link *left_type   = (left  ? operandType(left)  : 0);
250     
251     /* if it is a pointer then return ok for now */
252     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
253     
254     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
255        so we will cse only if they are local (i.e. both ic & pdic belong to
256        the same basic block */
257     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
258         /* then if they are the same Basic block then ok */
259         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
260         else return 0;
261     }
262         
263     /* for others it is cheaper to do the cse */
264     return 1;
265 }
266 /** $1 is always the basename.
267     $2 is always the output file.
268     $3 varies
269     $l is the list of extra options that should be there somewhere...
270     MUST be terminated with a NULL.
271 */
272 static const char *_linkCmd[] =
273 {
274   "aslink", "-nf", "$1", NULL
275 };
276
277 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
278 {
279   "asx8051", "$l", "$3", "$1.asm", NULL
280 };
281
282 /* Globals */
283 PORT ds390_port =
284 {
285   TARGET_ID_DS390,
286   "ds390",
287   "DS80C390",                   /* Target name */
288   {
289     TRUE,                       /* Emit glue around main */
290     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
291     MODEL_SMALL
292   },
293   {
294     _asmCmd,
295     NULL,
296     "-plosgffc",                /* Options with debug */
297     "-plosgff",                 /* Options without debug */
298     0,
299     ".asm"
300   },
301   {
302     _linkCmd,
303     NULL,
304     NULL,
305     ".rel"
306   },
307   {
308     _defaultRules
309   },
310   {
311         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
312     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
313   },
314   {
315     "XSEG    (XDATA)",
316     "STACK   (DATA)",
317     "CSEG    (CODE)",
318     "DSEG    (DATA)",
319     "ISEG    (DATA)",
320     "XSEG    (XDATA)",
321     "BSEG    (BIT)",
322     "RSEG    (DATA)",
323     "GSINIT  (CODE)",
324     "OSEG    (OVR,DATA)",
325     "GSFINAL (CODE)",
326     "HOME    (CODE)",
327     "XISEG   (XDATA)", // initialized xdata
328     "XINIT   (CODE)", // a code copy of xiseg
329     NULL,
330     NULL,
331     1
332   },
333   {
334     +1, 1, 4, 1, 1, 0
335   },
336     /* ds390 has an 16 bit mul & div */
337   {
338     2, -1
339   },
340   "_",
341   _ds390_init,
342   _ds390_parseOptions,
343   _ds390_finaliseOptions,
344   _ds390_setDefaultOptions,
345   ds390_assignRegisters,
346   _ds390_getRegName,
347   _ds390_keywords,
348   _ds390_genAssemblerPreamble,
349   _ds390_genIVT,
350   _ds390_genXINIT,
351   _ds390_reset_regparm,
352   _ds390_regparm,
353   NULL,
354   NULL,
355   NULL,
356   FALSE,
357   0,                            /* leave lt */
358   0,                            /* leave gt */
359   1,                            /* transform <= to ! > */
360   1,                            /* transform >= to ! < */
361   1,                            /* transform != to !(a == b) */
362   0,                            /* leave == */
363   TRUE,                         /* we support array initializers. */
364   cseCostEstimation,
365   __ds390_builtins,             /* table of builtin functions */
366   PORT_MAGIC
367 };