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