Break DS80C390 support into seperate port (ds390); first pass at spilling temporaries...
[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     "at",
20     "bit",
21     "code",
22     "critical",
23     "data",
24     "far",
25     "idata",
26     "interrupt",
27     "near",
28     "pdata",
29     "reentrant",
30     "sfr",
31     "sbit",
32     "using",
33     "xdata",
34     "_data",
35     "_code",
36     "_generic",
37     "_near",
38     "_xdata",
39     "_pdata",
40     "_idata",
41     NULL
42 };
43
44
45 void ds390_assignRegisters (eBBlock **ebbs, int count);
46
47 static int regParmFlg = 0; /* determine if we can register a parameter */
48
49 static void _ds390_init(void)
50 {
51     asm_addTree(&asm_asxxxx_mapping);
52 }
53
54 static void _ds390_reset_regparm()
55 {
56     regParmFlg = 0;
57 }
58
59 static int _ds390_regparm( link *l)
60 {
61     /* for this processor it is simple
62        can pass only the first parameter in a register */
63     if (regParmFlg)
64         return 0;
65
66     regParmFlg = 1;
67     return 1;
68 }
69
70 static bool _ds390_parseOptions(int *pargc, char **argv, int *i)
71 {
72     /* TODO: allow port-specific command line options to specify
73      * segment names here.
74      */
75     return FALSE;
76 }
77
78 static void _ds390_finaliseOptions(void)
79 {
80     /* Hack-o-matic: if we are using the flat24 model,
81      * adjust pointer sizes.
82      */
83     if (options.model != MODEL_FLAT24)
84     {
85         fprintf(stderr, 
86                 "*** warning: ds390 port only supports the flat24 model.\n");    
87         options.model = MODEL_FLAT24;
88     }
89     port->s.fptr_size = 3;
90     port->s.gptr_size = 4;
91     port->stack.isr_overhead++;   /* Will save dpx on ISR entry. */
92 #if 1
93     port->stack.call_overhead++;           /* This acounts for the extra byte 
94                                             * of return addres on the stack.
95                                             * but is ugly. There must be a 
96                                             * better way.
97                                             */
98 #endif
99
100     if (options.model) {
101         port->mem.default_local_map = xdata;
102         port->mem.default_globl_map = xdata;
103     } else {
104         port->mem.default_local_map = data;
105         port->mem.default_globl_map = data;
106     }
107     
108     if (options.stack10bit)
109     {
110         if (options.model != MODEL_FLAT24)
111         {
112             fprintf(stderr, 
113                     "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
114             fprintf(stderr, "\t10 bit stack mode disabled.\n");
115             options.stack10bit = 0;
116         }
117         else
118         {
119             /* Fixup the memory map for the stack; it is now in
120              * far space and requires a FPOINTER to access it.
121              */
122             istack->fmap = 1;
123             istack->ptrType = FPOINTER; 
124         }
125     }
126 }
127
128 static void _ds390_setDefaultOptions(void)
129 {
130 }
131
132 static const char *_ds390_getRegName(struct regs *reg)
133 {
134     if (reg)
135         return reg->name;
136     return "err";
137 }
138
139 static void _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 _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     "aslink", "-nf", "$1", NULL
190 };
191
192 static const char *_asmCmd[] = {
193     "asx8051", "-plosgffc", "$1.asm", NULL
194 };
195
196 /* Globals */
197 PORT ds390_port = {
198     "ds390",
199     "DS80C390",                 /* Target name */
200     {
201         TRUE,                   /* Emit glue around main */
202         MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
203         MODEL_SMALL
204     },
205     {   
206         _asmCmd,
207         "-plosgffc",            /* Options with debug */
208         "-plosgff",             /* Options without debug */
209         0
210     },
211     {
212         _linkCmd,
213         NULL,
214         ".rel"
215     },
216     {
217         _defaultRules
218     },
219     {
220         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
221         1, 1, 2, 4, 1, 2, 3, 1, 4, 4
222     },
223     {
224         "XSEG    (XDATA)",
225         "STACK   (DATA)",
226         "CSEG    (CODE)",
227         "DSEG    (DATA)",
228         "ISEG    (DATA)",
229         "XSEG    (XDATA)",
230         "BSEG    (BIT)",
231         "RSEG    (DATA)",
232         "GSINIT  (CODE)",
233         "OSEG    (OVR,DATA)",
234         "GSFINAL (CODE)",
235         "HOME    (CODE)",
236         NULL,
237         NULL,
238         1
239     },
240     { 
241         +1, 1, 4, 1, 1, 0
242     },
243     /* ds390 has an 8 bit mul */
244     {
245         1
246     },
247     "_",
248     _ds390_init,
249     _ds390_parseOptions,
250     _ds390_finaliseOptions,
251     _ds390_setDefaultOptions,
252     ds390_assignRegisters,
253     _ds390_getRegName ,
254     _ds390_keywords,
255     _ds390_genAssemblerPreamble,
256     _ds390_genIVT ,
257     _ds390_reset_regparm,
258     _ds390_regparm,
259     NULL,
260     FALSE
261 };
262