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