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