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