Added tiniNative port
[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, "        orl     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   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
367   1,                            /* reset labelKey to 1 */
368   1,                            /* globals & local static allowed */
369   PORT_MAGIC
370 };
371
372 /*---------------------------------------------------------------------------------*/
373 /*                               TININative specific                               */
374 /*---------------------------------------------------------------------------------*/
375 /* Globals */
376 static void _tininative_init (void)
377 {
378     asm_addTree (&asm_a390_mapping);
379 }
380
381 static void _tininative_setDefaultOptions (void)
382 {
383     options.model=MODEL_FLAT24;
384     options.stack10bit=1;
385     options.stackAuto = 1;
386 }
387
388 static void _tininative_finaliseOptions (void)
389 {
390     /* Hack-o-matic: if we are using the flat24 model,
391      * adjust pointer sizes.
392      */
393     if (options.model != MODEL_FLAT24)  {
394         options.model = MODEL_FLAT24 ;
395         fprintf(stderr,"TININative supports only MODEL FLAT24\n");
396     }
397     port->s.fptr_size = 3;
398     port->s.gptr_size = 4;
399     
400     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
401     
402     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
403                                          * of return addres on the stack.
404                                          * but is ugly. There must be a 
405                                          * better way.
406                                          */
407     
408     port->mem.default_local_map = xdata;
409     port->mem.default_globl_map = xdata;
410     
411     if (!options.stack10bit) {
412         options.stack10bit = 1;
413         fprintf(stderr,"TININative supports only stack10bit \n");
414     }
415     
416     if (!options.stack_loc) options.stack_loc = 0x400007;
417     
418     /* generate native code 16*16 mul/div */
419     if (options.useAccelerator) 
420         port->support.muldiv=2;
421     else 
422         port->support.muldiv=1;
423     
424     /* Fixup the memory map for the stack; it is now in
425      * far space and requires a FPOINTER to access it.
426      */
427     istack->fmap = 1;
428     istack->ptrType = FPOINTER;
429     options.cc_only =1;
430 }  /* MODEL_FLAT24 */
431
432 static int _tininative_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts) 
433 {
434     return 1;
435 }
436 static void _tininative_genAssemblerPreamble (FILE * of)
437 {
438     fputs ("_bpx EQU 080h \t\t; _bpx register unknown to assembler\n", of);
439     fputs ("dpx EQU 093h\t\t; dpx register unknown to assembler\n", of);
440     fputs ("dps EQU 086h\t\t; dps register unknown to assembler\n", of);
441     fputs ("dpl1 EQU 084h\t\t; dpl1 register unknown to assembler\n", of);
442     fputs ("dph1 EQU 085h\t\t; dph1 register unknown to assembler\n", of);
443     fputs ("dpx1 EQU 095h\t\t; dpx1 register unknown to assembler\n", of);
444     fputs ("ap EQU 09Ch\t\t; ap register unknown to assembler\n", of);
445     fputs ("mcnt0 EQU 0D1h\t\t; mcnt0 register unknown to assembler\n", of);
446     fputs ("mcnt1 EQU 0D2h\t\t; mcnt1 register unknown to assembler\n", of);
447     fputs ("ma EQU 0D3h\t\t; ma register unknown to assembler\n", of);
448     fputs ("mb EQU 0D4h\t\t; mb register unknown to assembler\n", of);
449     fputs ("mc EQU 0D5h\t\t; mc register unknown to assembler\n", of);
450     fputs ("F1 EQU 0D1h\t\t; F1 user flag unknown to assembler\n", of);
451     fputs ("esp EQU 09Bh\t\t; ESP user flag unknown to assembler\n", of);
452 }
453
454 /* list of key words used by TININative */
455 static char *_tininative_keywords[] =
456 {
457   "at",
458   "bit",
459   "code",
460   "critical",
461   "data",
462   "far",
463   "idata",
464   "interrupt",
465   "near",
466   "pdata",
467   "reentrant",
468   "sfr",
469   "sbit",
470   "using",
471   "xdata",
472   "_data",
473   "_code",
474   "_generic",
475   "_near",
476   "_xdata",
477   "_pdata",
478   "_idata",
479   "_naked",
480   "_JavaNative",
481   NULL
482 };
483
484 static builtins __tininative_builtins[] = {
485     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
486     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
487     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
488     { NULL , NULL,0, {NULL}}                       /* mark end of table */
489 };    
490
491 static const char *_a390Cmd[] =
492 {
493   "a390", "$l", "$3", "$1.a51", NULL
494 };
495 PORT tininative_port =
496 {
497   TARGET_ID_DS390,
498   "TININative",
499   "DS80C390",                   /* Target name */
500   {
501     FALSE,                      /* Emit glue around main */
502     MODEL_FLAT24,
503     MODEL_FLAT24
504   },
505   {
506     _a390Cmd,
507     NULL,
508     "-l",               /* Options with debug */
509     "-l",               /* Options without debug */
510     0,
511     ".a51"
512   },
513   {
514     NULL,
515     NULL,
516     NULL,
517     ".tlib",
518   },
519   {
520     _defaultRules
521   },
522   {
523         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
524     1, 2, 2, 4, 1, 3, 3, 1, 4, 4
525   },
526   {
527     "XSEG    (XDATA)",
528     "STACK   (DATA)",
529     "CSEG    (CODE)",
530     "DSEG    (DATA)",
531     "ISEG    (DATA)",
532     "XSEG    (XDATA)",
533     "BSEG    (BIT)",
534     "RSEG    (DATA)",
535     "GSINIT  (CODE)",
536     "OSEG    (OVR,DATA)",
537     "GSFINAL (CODE)",
538     "HOME        (CODE)",
539     NULL,
540     NULL,
541     NULL,
542     NULL,
543     1
544   },
545   {
546     +1, 1, 4, 1, 1, 0
547   },
548     /* ds390 has an 16 bit mul & div */
549   {
550     2, -1
551   },
552   "",
553   _tininative_init,
554   _ds390_parseOptions,
555   _tininative_finaliseOptions,
556   _tininative_setDefaultOptions,
557   ds390_assignRegisters,
558   _ds390_getRegName,
559   _tininative_keywords,
560   _tininative_genAssemblerPreamble,
561   _tininative_genIVT,
562   NULL,
563   _ds390_reset_regparm,
564   _ds390_regparm,
565   NULL,
566   NULL,
567   NULL,
568   FALSE,
569   0,                            /* leave lt */
570   0,                            /* leave gt */
571   1,                            /* transform <= to ! > */
572   1,                            /* transform >= to ! < */
573   1,                            /* transform != to !(a == b) */
574   0,                            /* leave == */
575   TRUE,                         /* we support array initializers. */
576   cseCostEstimation,
577   __tininative_builtins,        /* table of builtin functions */
578   FPOINTER,                     /* treat unqualified pointers as far pointers */
579   0,                            /* DONOT reset labelKey */
580   0,                            /* globals & local static NOT allowed */
581   PORT_MAGIC
582 };