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