fixed undefined _ESP in main.c
[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 += 2;      /* Will save dpx on ISR entry. */
109
110     port->stack.call_overhead += 2;     /* 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     /* generate native code 16*16 mul/div */
126     if (options.useAccelerator) 
127             port->support.muldiv=2;
128     else 
129             port->support.muldiv=1;
130
131      /* Fixup the memory map for the stack; it is now in
132      * far space and requires a FPOINTER to access it.
133      */
134     istack->fmap = 1;
135     istack->ptrType = FPOINTER;
136   }  /* MODEL_FLAT24 */
137 }
138
139 static void
140 _ds390_setDefaultOptions (void)
141 {
142   options.model=MODEL_FLAT24;
143   options.stack10bit=1;
144 }
145
146 static const char *
147 _ds390_getRegName (struct regs *reg)
148 {
149   if (reg)
150     return reg->name;
151   return "err";
152 }
153
154 static void
155 _ds390_genAssemblerPreamble (FILE * of)
156 {
157       if (options.model == MODEL_FLAT24)
158         fputs (".flat24 on\t\t; 24 bit flat addressing\n", of);
159
160       fputs ("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
161       fputs ("dps = 0x86\t\t; dps register unknown to assembler\n", of);
162       fputs ("dpl1 = 0x84\t\t; dpl1 register unknown to assembler\n", of);
163       fputs ("dph1 = 0x85\t\t; dph1 register unknown to assembler\n", of);
164       fputs ("dpx1 = 0x95\t\t; dpx1 register unknown to assembler\n", of);
165       fputs ("ap = 0x9C\t\t; ap register unknown to assembler\n", of);
166       fputs ("mcnt0 = 0xD1\t\t; mcnt0 register unknown to assembler\n", of);
167       fputs ("mcnt1 = 0xD2\t\t; mcnt1 register unknown to assembler\n", of);
168       fputs ("ma = 0xD3\t\t; ma register unknown to assembler\n", of);
169       fputs ("mb = 0xD4\t\t; mb register unknown to assembler\n", of);
170       fputs ("mc = 0xD5\t\t; mc register unknown to assembler\n", of);
171       fputs ("F1 = 0xD1\t\t; F1 user flag unknown to assembler\n", of);
172       fputs ("_ESP = 0x9B\t\t; ESP user flag unknown to assembler\n", of);
173 }
174
175 /* Generate interrupt vector table. */
176 static int
177 _ds390_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
178 {
179   int i;
180
181   if (options.model != MODEL_FLAT24)
182     {
183       /* Let the default code handle it. */
184       return FALSE;
185     }
186
187   fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
188
189   /* now for the other interrupts */
190   for (i = 0; i < maxInterrupts; i++)
191     {
192       if (interrupts[i])
193         {
194           fprintf (of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
195         }
196       else
197         {
198           fprintf (of, "\treti\n\t.ds\t7\n");
199         }
200     }
201
202   return TRUE;
203 }
204
205 /* Do CSE estimation */
206 static bool cseCostEstimation (iCode *ic, iCode *pdic)
207 {
208     operand *result = IC_RESULT(ic);
209     //operand *right  = IC_RIGHT(ic);
210     //operand *left   = IC_LEFT(ic);
211     sym_link *result_type = operandType(result);
212     //sym_link *right_type  = (right ? operandType(right) : 0);
213     //sym_link *left_type   = (left  ? operandType(left)  : 0);
214     
215     /* if it is a pointer then return ok for now */
216     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
217     
218     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
219        so we will cse only if they are local (i.e. both ic & pdic belong to
220        the same basic block */
221     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
222         /* then if they are the same Basic block then ok */
223         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
224         else return 0;
225     }
226         
227     /* for others it is cheaper to do the cse */
228     return 1;
229 }
230 /** $1 is always the basename.
231     $2 is always the output file.
232     $3 varies
233     $l is the list of extra options that should be there somewhere...
234     MUST be terminated with a NULL.
235 */
236 static const char *_linkCmd[] =
237 {
238   "aslink", "-nf", "$1", NULL
239 };
240
241 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */   static const char *_asmCmd[] =
242 {
243   "asx8051", "$l", "$3", "$1.asm", NULL
244 };
245
246 /* Globals */
247 PORT ds390_port =
248 {
249   TARGET_ID_DS390,
250   "ds390",
251   "DS80C390",                   /* Target name */
252   {
253     TRUE,                       /* Emit glue around main */
254     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
255     MODEL_SMALL
256   },
257   {
258     _asmCmd,
259     NULL,
260     "-plosgffc",                /* Options with debug */
261     "-plosgff",                 /* Options without debug */
262     0,
263     ".asm"
264   },
265   {
266     _linkCmd,
267     NULL,
268     NULL,
269     ".rel"
270   },
271   {
272     _defaultRules
273   },
274   {
275         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
276     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
277   },
278   {
279     "XSEG    (XDATA)",
280     "STACK   (DATA)",
281     "CSEG    (CODE)",
282     "DSEG    (DATA)",
283     "ISEG    (DATA)",
284     "XSEG    (XDATA)",
285     "BSEG    (BIT)",
286     "RSEG    (DATA)",
287     "GSINIT  (CODE)",
288     "OSEG    (OVR,DATA)",
289     "GSFINAL (CODE)",
290     "HOME        (CODE)",
291     NULL,
292     NULL,
293     1
294   },
295   {
296     +1, 1, 4, 1, 1, 0
297   },
298     /* ds390 has an 16 bit mul & div */
299   {
300     2, -1
301   },
302   "_",
303   _ds390_init,
304   _ds390_parseOptions,
305   _ds390_finaliseOptions,
306   _ds390_setDefaultOptions,
307   ds390_assignRegisters,
308   _ds390_getRegName,
309   _ds390_keywords,
310   _ds390_genAssemblerPreamble,
311   _ds390_genIVT,
312   _ds390_reset_regparm,
313   _ds390_regparm,
314   NULL,
315   NULL,
316   NULL,
317   FALSE,
318   0,                            /* leave lt */
319   0,                            /* leave gt */
320   1,                            /* transform <= to ! > */
321   1,                            /* transform >= to ! < */
322   1,                            /* transform != to !(a == b) */
323   0,                            /* leave == */
324   TRUE,                         /* we support array initializers. */
325   cseCostEstimation,
326   PORT_MAGIC
327 };