ALPHA version for -mTININative
[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 #include "BuildCmd.h"
12 #include "MySystem.h"
13
14 static char _defaultRules[] =
15 {
16 #include "peeph.rul"
17 };
18
19 /* list of key words used by msc51 */
20 static char *_ds390_keywords[] =
21 {
22   "at",
23   "bit",
24   "code",
25   "critical",
26   "data",
27   "far",
28   "idata",
29   "interrupt",
30   "near",
31   "pdata",
32   "reentrant",
33   "sfr",
34   "sbit",
35   "using",
36   "xdata",
37   "_data",
38   "_code",
39   "_generic",
40   "_near",
41   "_xdata",
42   "_pdata",
43   "_idata",
44   "_naked",
45   NULL
46 };
47
48 static builtins __ds390_builtins[] = {
49     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
50     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
51     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
52     { NULL , NULL,0, {NULL}}                       /* mark end of table */
53 };    
54 void ds390_assignRegisters (eBBlock ** ebbs, int count);
55
56 static int regParmFlg = 0;      /* determine if we can register a parameter */
57
58 static void
59 _ds390_init (void)
60 {
61   asm_addTree (&asm_asxxxx_mapping);
62 }
63
64 static void
65 _ds390_reset_regparm ()
66 {
67   regParmFlg = 0;
68 }
69
70 static int
71 _ds390_regparm (sym_link * l)
72 {
73   /* for this processor it is simple
74      can pass only the first parameter in a register */
75   if (regParmFlg)
76     return 0;
77
78   regParmFlg = 1;
79   return 1;
80 }
81
82 static bool
83 _ds390_parseOptions (int *pargc, char **argv, int *i)
84 {
85   /* TODO: allow port-specific command line options to specify
86    * segment names here.
87    */
88   return FALSE;
89 }
90
91 static void
92 _ds390_finaliseOptions (void)
93 {
94   /* Hack-o-matic: if we are using the flat24 model,
95    * adjust pointer sizes.
96    */
97   if (options.model != MODEL_FLAT24)  {
98       fprintf (stderr,
99                "*** warning: ds390 port small and large model experimental.\n");
100       if (options.model == MODEL_LARGE)
101       {
102         port->mem.default_local_map = xdata;
103         port->mem.default_globl_map = xdata;
104       }
105       else
106       {
107         port->mem.default_local_map = data;
108         port->mem.default_globl_map = data;
109       }
110   }
111   else {
112     port->s.fptr_size = 3;
113     port->s.gptr_size = 4;
114
115     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
116
117     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
118                                  * of return addres on the stack.
119                                  * but is ugly. There must be a 
120                                  * better way.
121                                  */
122
123     port->mem.default_local_map = xdata;
124     port->mem.default_globl_map = xdata;
125
126     if (!options.stack10bit)
127     {
128     fprintf (stderr,
129              "*** error: ds390 port only supports the 10 bit stack mode.\n");
130     } else {
131         if (!options.stack_loc) options.stack_loc = 0x400007;
132     }
133     
134     /* generate native code 16*16 mul/div */
135     if (options.useAccelerator) 
136             port->support.muldiv=2;
137     else 
138             port->support.muldiv=1;
139
140      /* Fixup the memory map for the stack; it is now in
141      * far space and requires a FPOINTER to access it.
142      */
143     istack->fmap = 1;
144     istack->ptrType = FPOINTER;
145   }  /* MODEL_FLAT24 */
146 }
147
148 static void
149 _ds390_setDefaultOptions (void)
150 {
151   options.model=MODEL_FLAT24;
152   options.stack10bit=1;
153 }
154
155 static const char *
156 _ds390_getRegName (struct regs *reg)
157 {
158   if (reg)
159     return reg->name;
160   return "err";
161 }
162
163 static void
164 _ds390_genAssemblerPreamble (FILE * of)
165 {
166       if (options.model == MODEL_FLAT24)
167         fputs (".flat24 on\t\t; 24 bit flat addressing\n", of);
168
169       fputs ("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
170       fputs ("dps = 0x86\t\t; dps register unknown to assembler\n", of);
171       fputs ("dpl1 = 0x84\t\t; dpl1 register unknown to assembler\n", of);
172       fputs ("dph1 = 0x85\t\t; dph1 register unknown to assembler\n", of);
173       fputs ("dpx1 = 0x95\t\t; dpx1 register unknown to assembler\n", of);
174       fputs ("ap = 0x9C\t\t; ap register unknown to assembler\n", of);
175       fputs ("_ap = 0x9C\t\t; _ap register unknown to assembler\n", of);
176       fputs ("mcnt0 = 0xD1\t\t; mcnt0 register unknown to assembler\n", of);
177       fputs ("mcnt1 = 0xD2\t\t; mcnt1 register unknown to assembler\n", of);
178       fputs ("ma = 0xD3\t\t; ma register unknown to assembler\n", of);
179       fputs ("mb = 0xD4\t\t; mb register unknown to assembler\n", of);
180       fputs ("mc = 0xD5\t\t; mc register unknown to assembler\n", of);
181       fputs ("F1 = 0xD1\t\t; F1 user flag unknown to assembler\n", of);
182       fputs ("esp = 0x9B\t\t; ESP user flag unknown to assembler\n", of);
183 }
184
185 /* Generate interrupt vector table. */
186 static int
187 _ds390_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
188 {
189   int i;
190
191   if (options.model != MODEL_FLAT24)
192     {
193       /* Let the default code handle it. */
194       return FALSE;
195     }
196
197   fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
198
199   /* now for the other interrupts */
200   for (i = 0; i < maxInterrupts; i++)
201     {
202       if (interrupts[i])
203         {
204           fprintf (of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
205         }
206       else
207         {
208           fprintf (of, "\treti\n\t.ds\t7\n");
209         }
210     }
211
212   return TRUE;
213 }
214
215 /* Generate code to copy XINIT to XISEG */
216 static void _ds390_genXINIT (FILE * of) {
217   fprintf (of, ";       _ds390_genXINIT() start\n");
218   fprintf (of, "        mov     a,#l_XINIT\n");
219   fprintf (of, "        orl     a,#l_XINIT>>8\n");
220   fprintf (of, "        jz      00003$\n");
221   fprintf (of, "        mov     a,#s_XINIT\n");
222   fprintf (of, "        add     a,#l_XINIT\n");
223   fprintf (of, "        mov     r1,a\n");
224   fprintf (of, "        mov     a,#s_XINIT>>8\n");
225   fprintf (of, "        addc    a,#l_XINIT>>8\n");
226   fprintf (of, "        mov     r2,a\n");
227   fprintf (of, "        mov     dptr,#s_XINIT\n");
228   fprintf (of, "        mov     dps,#0x21\n");
229   fprintf (of, "        mov     dptr,#s_XISEG\n");
230   fprintf (of, "00001$: clr     a\n");
231   fprintf (of, "        movc    a,@a+dptr\n");
232   fprintf (of, "        movx    @dptr,a\n");
233   fprintf (of, "        inc     dptr\n");
234   fprintf (of, "        inc     dptr\n");
235   fprintf (of, "00002$: mov     a,dpl\n");
236   fprintf (of, "        cjne    a,ar1,00001$\n");
237   fprintf (of, "        mov     a,dph\n");
238   fprintf (of, "        cjne    a,ar2,00001$\n");
239   fprintf (of, "        mov     dps,#0\n");
240   fprintf (of, "00003$:\n");
241   fprintf (of, ";       _ds390_genXINIT() end\n");
242 }
243
244 /* Do CSE estimation */
245 static bool cseCostEstimation (iCode *ic, iCode *pdic)
246 {
247     operand *result = IC_RESULT(ic);
248     //operand *right  = IC_RIGHT(ic);
249     //operand *left   = IC_LEFT(ic);
250     sym_link *result_type = operandType(result);
251     //sym_link *right_type  = (right ? operandType(right) : 0);
252     //sym_link *left_type   = (left  ? operandType(left)  : 0);
253     
254     /* if it is a pointer then return ok for now */
255     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
256     
257     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
258        so we will cse only if they are local (i.e. both ic & pdic belong to
259        the same basic block */
260     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
261         /* then if they are the same Basic block then ok */
262         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
263         else return 0;
264     }
265         
266     /* for others it is cheaper to do the cse */
267     return 1;
268 }
269 /** $1 is always the basename.
270     $2 is always the output file.
271     $3 varies
272     $l is the list of extra options that should be there somewhere...
273     MUST be terminated with a NULL.
274 */
275 static const char *_linkCmd[] =
276 {
277   "aslink", "-nf", "$1", NULL
278 };
279
280 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
281 {
282   "asx8051", "$l", "$3", "$1.asm", NULL
283 };
284
285 /* Globals */
286 PORT ds390_port =
287 {
288   TARGET_ID_DS390,
289   "ds390",
290   "DS80C390",                   /* Target name */
291   {
292     TRUE,                       /* Emit glue around main */
293     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
294     MODEL_SMALL
295   },
296   {
297     _asmCmd,
298     NULL,
299     "-plosgffc",                /* Options with debug */
300     "-plosgff",                 /* Options without debug */
301     0,
302     ".asm",
303     NULL                        /* no do_assemble function */
304   },
305   {
306     _linkCmd,
307     NULL,
308     NULL,
309     ".rel"
310   },
311   {
312     _defaultRules
313   },
314   {
315         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
316     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
317   },
318   {
319     "XSEG    (XDATA)",
320     "STACK   (DATA)",
321     "CSEG    (CODE)",
322     "DSEG    (DATA)",
323     "ISEG    (DATA)",
324     "XSEG    (XDATA)",
325     "BSEG    (BIT)",
326     "RSEG    (DATA)",
327     "GSINIT  (CODE)",
328     "OSEG    (OVR,DATA)",
329     "GSFINAL (CODE)",
330     "HOME    (CODE)",
331     "XISEG   (XDATA)", // initialized xdata
332     "XINIT   (CODE)", // a code copy of xiseg
333     NULL,
334     NULL,
335     1
336   },
337   {
338     +1, 1, 4, 1, 1, 0
339   },
340     /* ds390 has an 16 bit mul & div */
341   {
342     2, -1
343   },
344   "_",
345   _ds390_init,
346   _ds390_parseOptions,
347   _ds390_finaliseOptions,
348   _ds390_setDefaultOptions,
349   ds390_assignRegisters,
350   _ds390_getRegName,
351   _ds390_keywords,
352   _ds390_genAssemblerPreamble,
353   NULL,                         /* no genAssemblerEnd */
354   _ds390_genIVT,
355   _ds390_genXINIT,
356   _ds390_reset_regparm,
357   _ds390_regparm,
358   NULL,
359   NULL,
360   NULL,
361   FALSE,
362   0,                            /* leave lt */
363   0,                            /* leave gt */
364   1,                            /* transform <= to ! > */
365   1,                            /* transform >= to ! < */
366   1,                            /* transform != to !(a == b) */
367   0,                            /* leave == */
368   TRUE,                         /* we support array initializers. */
369   cseCostEstimation,
370   __ds390_builtins,             /* table of builtin functions */
371   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
372   1,                            /* reset labelKey to 1 */
373   1,                            /* globals & local static allowed */
374   PORT_MAGIC
375 };
376
377 /*---------------------------------------------------------------------------------*/
378 /*                               TININative specific                               */
379 /*---------------------------------------------------------------------------------*/
380 /* Globals */
381 static void _tininative_init (void)
382 {
383     asm_addTree (&asm_a390_mapping);
384 }
385
386 static void _tininative_setDefaultOptions (void)
387 {
388     options.model=MODEL_FLAT24;
389     options.stack10bit=1;
390     options.stackAuto = 1;
391 }
392
393 static void _tininative_finaliseOptions (void)
394 {
395     /* Hack-o-matic: if we are using the flat24 model,
396      * adjust pointer sizes.
397      */
398     if (options.model != MODEL_FLAT24)  {
399         options.model = MODEL_FLAT24 ;
400         fprintf(stderr,"TININative supports only MODEL FLAT24\n");
401     }
402     port->s.fptr_size = 3;
403     port->s.gptr_size = 4;
404     
405     port->stack.isr_overhead += 2;      /* Will save dpx on ISR entry. */
406     
407     port->stack.call_overhead += 2;     /* This acounts for the extra byte 
408                                          * of return addres on the stack.
409                                          * but is ugly. There must be a 
410                                          * better way.
411                                          */
412     
413     port->mem.default_local_map = xdata;
414     port->mem.default_globl_map = xdata;
415     
416     if (!options.stack10bit) {
417         options.stack10bit = 1;
418         fprintf(stderr,"TININative supports only stack10bit \n");
419     }
420     
421     if (!options.stack_loc) options.stack_loc = 0x400007;
422     
423     /* generate native code 16*16 mul/div */
424     if (options.useAccelerator) 
425         port->support.muldiv=2;
426     else 
427         port->support.muldiv=1;
428     
429     /* Fixup the memory map for the stack; it is now in
430      * far space and requires a FPOINTER to access it.
431      */
432     istack->fmap = 1;
433     istack->ptrType = FPOINTER;
434     options.cc_only =1;
435 }
436
437 static int _tininative_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts) 
438 {
439     return 1;
440 }
441 static void _tininative_genAssemblerPreamble (FILE * of)
442 {
443     fputs("$include(tini.inc)\n", of);
444     fputs("$include(ds80c390.inc)\n", of);
445     fputs("$include(tinimacro.inc)\n", of);
446     fputs("$include(apiequ.inc)\n", of);
447     fputs("_bpx EQU 01Eh \t\t; _bpx (frame pointer) mapped to R8_B3:R7_B3\n", of);
448     fputs("_ap  EQU 01Dh \t\t; _ap mapped to R6_B3\n", of);
449     /* Must be first and return 0 */
450     fputs("Lib_Native_Init:\n",of);
451     fputs("\tclr\ta\n",of);
452     fputs("\tret\n",of);
453     fputs("LibraryID:\n",of);
454     fputs("\tdb \"DS\"\n",of);
455     if (options.tini_libid) {
456         fprintf(of,"\tdb 0,0,0%02xh,0%02xh,0%02xh,0%02xh\n",
457                 (options.tini_libid>>24 & 0xff),
458                 (options.tini_libid>>16 & 0xff),
459                 (options.tini_libid>>8 & 0xff),
460                 (options.tini_libid  & 0xff));
461     } else {
462         fprintf(of,"\tdb 0,0,0,0,0,1\n");
463     }
464
465 }
466 static void _tininative_genAssemblerEnd (FILE * of)
467 {
468     fputs("\tend\n",of);
469 }
470 /* tininative assembler , calls "macro", if it succeeds calls "a390" */
471 static void _tininative_do_assemble (const char * const *asmOptions)
472 {
473     static const char *macroCmd[] = {
474         "macro","$1.a51",NULL
475     };
476     static const char *a390Cmd[] = {
477         "a390","$1.mpp",NULL
478     };
479     char buffer[100];
480
481     buildCmdLine(buffer,macroCmd,srcFileName,NULL,NULL,NULL);
482     if (my_system(buffer)) {
483         exit(1);
484     }
485     buildCmdLine(buffer,a390Cmd,srcFileName,NULL,NULL,asmOptions);
486     if (my_system(buffer)) {
487         exit(1);
488     }    
489 }
490
491 /* list of key words used by TININative */
492 static char *_tininative_keywords[] =
493 {
494   "at",
495   "bit",
496   "code",
497   "critical",
498   "data",
499   "far",
500   "idata",
501   "interrupt",
502   "near",
503   "pdata",
504   "reentrant",
505   "sfr",
506   "sbit",
507   "using",
508   "xdata",
509   "_data",
510   "_code",
511   "_generic",
512   "_near",
513   "_xdata",
514   "_pdata",
515   "_idata",
516   "_naked",
517   "_JavaNative",
518   NULL
519 };
520
521 static builtins __tininative_builtins[] = {
522     { "__builtin_memcpy_x2x","v",3,{"cx*","cx*","i"}}, /* void __builtin_memcpy_x2x (xdata char *,xdata char *,int) */
523     { "__builtin_memcpy_c2x","v",3,{"cx*","cp*","i"}}, /* void __builtin_memcpy_c2x (xdata char *,code  char *,int) */
524     { "__builtin_memset_x","v",3,{"cx*","c","i"}},     /* void __builtin_memset     (xdata char *,char,int)         */
525     /* TINI NatLib */
526     { "NatLib_LoadByte","c",1,{"c"}},                  /* char  Natlib_LoadByte  (0 based parameter number)         */
527     { "NatLib_LoadShort","s",1,{"c"}},                 /* short Natlib_LoadShort (0 based parameter number)         */
528     { "NatLib_LoadInt","l",1,{"c"}},                   /* long  Natlib_LoadLong  (0 based parameter number)         */
529     { "NatLib_LoadPointer","cx*",1,{"c"}},             /* long  Natlib_LoadPointer  (0 based parameter number)      */
530     /* TINI StateBlock related */
531     { "NatLib_InstallImmutableStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallImmutableStateBlock(state block *,int handle) */
532     { "NatLib_InstallEphemeralStateBlock","c",2,{"vx*","us"}},/* char NatLib_InstallEphemeralStateBlock(state block *,int handle) */
533     { "NatLib_RemoveImmutableStateBlock","v",0,{NULL}},/* void NatLib_RemoveImmutableStateBlock() */
534     { "NatLib_RemoveEphemeralStateBlock","v",0,{NULL}},/* void NatLib_RemoveEphemeralStateBlock() */
535     { "NatLib_GetImmutableStateBlock","i",0,{NULL}},   /* int  NatLib_GetImmutableStateBlock () */
536     { "NatLib_GetEphemeralStateBlock","i",0,{NULL}},   /* int  NatLib_GetEphemeralStateBlock () */
537     /* Memory manager */
538     { "MM_XMalloc","i",1,{"l"}},                       /* int  MM_XMalloc (long)                */
539     { "MM_Malloc","i",1,{"i"}},                        /* int  MM_Malloc  (int)                 */
540     { "MM_ApplicationMalloc","i",1,{"i"}},             /* int  MM_ApplicationMalloc  (int)      */
541     { "MM_Free","i",1,{"i"}},                          /* int  MM_Free  (int)                   */
542     { "MM_Deref","cx*",1,{"i"}},                       /* char *MM_Free  (int)                  */
543     { "MM_UnrestrictedPersist","c",1,{"i"}},           /* char  MM_UnrestrictedPersist  (int)   */
544     { "MM_AppTag","c",2,{"i","c"}},                    /* char *MM_AppTag  (int,char)           */
545     { NULL , NULL,0, {NULL}}                       /* mark end of table */
546 };    
547
548 static const char *_a390Cmd[] =
549 {
550   "macro", "$l", "$3", "$1.a51", NULL
551 };
552 PORT tininative_port =
553 {
554   TARGET_ID_DS390,
555   "TININative",
556   "DS80C390",                   /* Target name */
557   {
558     FALSE,                      /* Emit glue around main */
559     MODEL_FLAT24,
560     MODEL_FLAT24
561   },
562   {
563     _a390Cmd,
564     NULL,
565     "-l",               /* Options with debug */
566     "-l",               /* Options without debug */
567     0,
568     ".a51",
569     _tininative_do_assemble
570   },
571   {
572     NULL,
573     NULL,
574     NULL,
575     ".tlib",
576   },
577   {
578     _defaultRules
579   },
580   {
581         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
582     1, 2, 2, 4, 1, 3, 3, 1, 4, 4
583   },
584   {
585     "XSEG    (XDATA)",
586     "STACK   (DATA)",
587     "CSEG    (CODE)",
588     "DSEG    (DATA)",
589     "ISEG    (DATA)",
590     "XSEG    (XDATA)",
591     "BSEG    (BIT)",
592     "RSEG    (DATA)",
593     "GSINIT  (CODE)",
594     "OSEG    (OVR,DATA)",
595     "GSFINAL (CODE)",
596     "HOME        (CODE)",
597     NULL,
598     NULL,
599     NULL,
600     NULL,
601     1
602   },
603   {
604     +1, 1, 4, 1, 1, 0
605   },
606     /* ds390 has an 16 bit mul & div */
607   {
608     2, -1
609   },
610   "",
611   _tininative_init,
612   _ds390_parseOptions,
613   _tininative_finaliseOptions,
614   _tininative_setDefaultOptions,
615   ds390_assignRegisters,
616   _ds390_getRegName,
617   _tininative_keywords,
618   _tininative_genAssemblerPreamble,
619   _tininative_genAssemblerEnd,
620   _tininative_genIVT,
621   NULL,
622   _ds390_reset_regparm,
623   _ds390_regparm,
624   NULL,
625   NULL,
626   NULL,
627   FALSE,
628   0,                            /* leave lt */
629   0,                            /* leave gt */
630   1,                            /* transform <= to ! > */
631   1,                            /* transform >= to ! < */
632   1,                            /* transform != to !(a == b) */
633   0,                            /* leave == */
634   TRUE,                         /* we support array initializers. */
635   cseCostEstimation,
636   __tininative_builtins,        /* table of builtin functions */
637   FPOINTER,                     /* treat unqualified pointers as far pointers */
638   0,                            /* DONOT reset labelKey */
639   0,                            /* globals & local static NOT allowed */
640   PORT_MAGIC
641 };