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