some small corrections
[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,#s_XINIT\n");
216   fprintf (of, "        add     a,#l_XINIT\n");
217   fprintf (of, "        mov     r1,a\n");
218   fprintf (of, "        mov     a,#s_XINIT>>8\n");
219   fprintf (of, "        addc    a,#l_XINIT>>8\n");
220   fprintf (of, "        mov     r2,a\n");
221   fprintf (of, "        mov     dptr,#s_XINIT\n");
222   fprintf (of, "        mov     dps,#0x21\n");
223   fprintf (of, "        mov     dptr,#s_XISEG\n");
224   fprintf (of, "00001$: clr     a\n");
225   fprintf (of, "        movc    a,@a+dptr\n");
226   fprintf (of, "        movx    @dptr,a\n");
227   fprintf (of, "        inc     dptr\n");
228   fprintf (of, "        inc     dptr\n");
229   fprintf (of, "00002$: mov     a,dpl\n");
230   fprintf (of, "        cjne    a,ar1,00001$\n");
231   fprintf (of, "        mov     a,dph\n");
232   fprintf (of, "        cjne    a,ar2,00001$\n");
233   fprintf (of, "        mov     dps,#0\n");
234   fprintf (of, ";       _ds390_genXINIT() end\n");
235 }
236
237 /* Do CSE estimation */
238 static bool cseCostEstimation (iCode *ic, iCode *pdic)
239 {
240     operand *result = IC_RESULT(ic);
241     //operand *right  = IC_RIGHT(ic);
242     //operand *left   = IC_LEFT(ic);
243     sym_link *result_type = operandType(result);
244     //sym_link *right_type  = (right ? operandType(right) : 0);
245     //sym_link *left_type   = (left  ? operandType(left)  : 0);
246     
247     /* if it is a pointer then return ok for now */
248     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
249     
250     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
251        so we will cse only if they are local (i.e. both ic & pdic belong to
252        the same basic block */
253     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
254         /* then if they are the same Basic block then ok */
255         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
256         else return 0;
257     }
258         
259     /* for others it is cheaper to do the cse */
260     return 1;
261 }
262 /** $1 is always the basename.
263     $2 is always the output file.
264     $3 varies
265     $l is the list of extra options that should be there somewhere...
266     MUST be terminated with a NULL.
267 */
268 static const char *_linkCmd[] =
269 {
270   "aslink", "-nf", "$1", NULL
271 };
272
273 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
274 {
275   "asx8051", "$l", "$3", "$1.asm", NULL
276 };
277
278 /* Globals */
279 PORT ds390_port =
280 {
281   TARGET_ID_DS390,
282   "ds390",
283   "DS80C390",                   /* Target name */
284   {
285     TRUE,                       /* Emit glue around main */
286     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
287     MODEL_SMALL
288   },
289   {
290     _asmCmd,
291     NULL,
292     "-plosgffc",                /* Options with debug */
293     "-plosgff",                 /* Options without debug */
294     0,
295     ".asm"
296   },
297   {
298     _linkCmd,
299     NULL,
300     NULL,
301     ".rel"
302   },
303   {
304     _defaultRules
305   },
306   {
307         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
308     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
309   },
310   {
311     "XSEG    (XDATA)",
312     "STACK   (DATA)",
313     "CSEG    (CODE)",
314     "DSEG    (DATA)",
315     "ISEG    (DATA)",
316     "XSEG    (XDATA)",
317     "BSEG    (BIT)",
318     "RSEG    (DATA)",
319     "GSINIT  (CODE)",
320     "OSEG    (OVR,DATA)",
321     "GSFINAL (CODE)",
322     "HOME    (CODE)",
323     "XISEG   (XDATA)", // initialized xdata
324     "XINIT   (CODE)", // a code copy of xiseg
325     NULL,
326     NULL,
327     1
328   },
329   {
330     +1, 1, 4, 1, 1, 0
331   },
332     /* ds390 has an 16 bit mul & div */
333   {
334     2, -1
335   },
336   "_",
337   _ds390_init,
338   _ds390_parseOptions,
339   _ds390_finaliseOptions,
340   _ds390_setDefaultOptions,
341   ds390_assignRegisters,
342   _ds390_getRegName,
343   _ds390_keywords,
344   _ds390_genAssemblerPreamble,
345   _ds390_genIVT,
346   _ds390_genXINIT,
347   _ds390_reset_regparm,
348   _ds390_regparm,
349   NULL,
350   NULL,
351   NULL,
352   FALSE,
353   0,                            /* leave lt */
354   0,                            /* leave gt */
355   1,                            /* transform <= to ! > */
356   1,                            /* transform >= to ! < */
357   1,                            /* transform != to !(a == b) */
358   0,                            /* leave == */
359   TRUE,                         /* we support array initializers. */
360   cseCostEstimation,
361   __ds390_builtins,             /* table of builtin functions */
362   PORT_MAGIC
363 };