Merge of the izt changes.
[fw/sdcc] / src / mcs51 / main.c
1 /** @file main.c
2     mcs51 specific general functions.
3
4     Note that mlh prepended _mcs51_ 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 *_mcs51_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 mcs51_assignRegisters (eBBlock **ebbs, int count);
46
47 static int regParmFlg = 0; /* determine if we can register a parameter */
48
49 static void _mcs51_init(void)
50 {
51     asm_addTree(&asm_asxxxx_mapping);
52 }
53
54 static void _mcs51_reset_regparm()
55 {
56     regParmFlg = 0;
57 }
58
59 static int _mcs51_regparm( sym_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 _mcs51_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 _mcs51_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         
86         fprintf(stderr, "*** WARNING: you should use the '-mds390' option "
87                         "for DS80C390 support. This code generator is "
88                         "badly out of date and probably broken.\n");
89         
90         port->s.fptr_size = 3;
91         port->s.gptr_size = 4;
92         port->stack.isr_overhead++;   /* Will save dpx on ISR entry. */
93         #if 1
94         port->stack.call_overhead++;       /* This acounts for the extra byte 
95                                             * of return addres on the stack.
96                                             * but is ugly. There must be a 
97                                             * better way.
98                                             */
99         #endif
100         fReturn = fReturn390;
101         fReturnSize = 5;
102     } 
103
104     if (options.model == MODEL_LARGE) {
105         port->mem.default_local_map = xdata;
106         port->mem.default_globl_map = xdata;
107     } else {
108         port->mem.default_local_map = data;
109         port->mem.default_globl_map = data;
110     }
111     
112     if (options.stack10bit)
113     {
114         if (options.model != MODEL_FLAT24)
115         {
116             fprintf(stderr, 
117                     "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
118             fprintf(stderr, "\t10 bit stack mode disabled.\n");
119             options.stack10bit = 0;
120         }
121         else
122         {
123             /* Fixup the memory map for the stack; it is now in
124              * far space and requires a FPOINTER to access it.
125              */
126             istack->fmap = 1;
127             istack->ptrType = FPOINTER; 
128         }
129     }
130 }
131
132 static void _mcs51_setDefaultOptions(void)
133 {
134 }
135
136 static const char *_mcs51_getRegName(struct regs *reg)
137 {
138     if (reg)
139         return reg->name;
140     return "err";
141 }
142
143 static void _mcs51_genAssemblerPreamble(FILE *of)
144 {
145    if (options.model == MODEL_FLAT24)
146    {
147        fputs(".flat24 on\t\t; 24 bit flat addressing\n", of);
148        fputs("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
149        fputs("dps = 0x86\t\t; dps register unknown to assembler\n", of);
150        fputs("dpl1 = 0x84\t\t; dpl1 register unknown to assembler\n", of);
151        fputs("dph1 = 0x85\t\t; dph1 register unknown to assembler\n", of);
152        fputs("dpx1 = 0x95\t\t; dpx1 register unknown to assembler\n", of);
153    }
154 }
155
156 /* Generate interrupt vector table. */
157 static int _mcs51_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
158 {
159     int i;
160     
161     if (options.model != MODEL_FLAT24)
162     {
163         /* Let the default code handle it. */
164         return FALSE;
165     }
166     
167     fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
168     
169     /* now for the other interrupts */
170     for (i = 0; i < maxInterrupts; i++) 
171     {
172         if (interrupts[i])
173         {
174             fprintf(of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
175         }
176         else
177         {
178             fprintf(of, "\treti\n\t.ds\t7\n");
179         }
180     }
181     
182     return TRUE;
183 }
184
185 /** $1 is always the basename.
186     $2 is always the output file.
187     $3 varies
188     $l is the list of extra options that should be there somewhere...
189     MUST be terminated with a NULL.
190 */
191 static const char *_linkCmd[] = {
192     "aslink", "-nf", "$1", NULL
193 };
194
195 static const char *_asmCmd[] = {
196     "asx8051", "-plosgffc", "$1.asm", NULL
197 };
198
199 /* Globals */
200 PORT mcs51_port = {
201     "mcs51",
202     "MCU 8051",                 /* Target name */
203     {
204         TRUE,                   /* Emit glue around main */
205         MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
206         MODEL_SMALL
207     },
208     {   
209         _asmCmd,
210         "-plosgffc",            /* Options with debug */
211         "-plosgff",             /* Options without debug */
212         0
213     },
214     {
215         _linkCmd,
216         NULL,
217         ".rel"
218     },
219     {
220         _defaultRules
221     },
222     {
223         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
224         1, 1, 2, 4, 1, 2, 3, 1, 4, 4
225     },
226     {
227         "XSEG    (XDATA)",
228         "STACK   (DATA)",
229         "CSEG    (CODE)",
230         "DSEG    (DATA)",
231         "ISEG    (DATA)",
232         "XSEG    (XDATA)",
233         "BSEG    (BIT)",
234         "RSEG    (DATA)",
235         "GSINIT  (CODE)",
236         "OSEG    (OVR,DATA)",
237         "GSFINAL (CODE)",
238         "HOME    (CODE)",
239         NULL,
240         NULL,
241         1
242     },
243     { 
244         +1, 1, 4, 1, 1, 0
245     },
246     /* mcs51 has an 8 bit mul */
247     {
248         1, 0
249     },
250     "_",
251     _mcs51_init,
252     _mcs51_parseOptions,
253     _mcs51_finaliseOptions,
254     _mcs51_setDefaultOptions,
255     mcs51_assignRegisters,
256     _mcs51_getRegName ,
257     _mcs51_keywords,
258     _mcs51_genAssemblerPreamble,
259     _mcs51_genIVT ,
260     _mcs51_reset_regparm,
261     _mcs51_regparm,
262     NULL,
263     FALSE,
264     0,  /* leave lt */
265     0,  /* leave gt */
266     1,  /* transform <= to ! > */
267     1,  /* transform >= to ! < */
268     1,  /* transform != to !(a == b) */
269     0,  /* leave == */
270     PORT_MAGIC
271 };
272