Merged changes between gbdk-293 and main
[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( 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         port->s.fptr_size = 3;
86         port->s.gptr_size = 4;
87         port->stack.isr_overhead++;   /* Will save dpx on ISR entry. */
88         #if 1
89         port->stack.call_overhead++;       /* This acounts for the extra byte 
90                                             * of return addres on the stack.
91                                             * but is ugly. There must be a 
92                                             * better way.
93                                             */
94         #endif
95         fReturn = fReturn390;
96         fReturnSize = 5;
97     } 
98
99     if (options.model) {
100         port->mem.default_local_map = xdata;
101         port->mem.default_globl_map = xdata;
102     } else {
103         port->mem.default_local_map = data;
104         port->mem.default_globl_map = data;
105     }
106     
107     if (options.stack10bit)
108     {
109         if (options.model != MODEL_FLAT24)
110         {
111             fprintf(stderr, 
112                     "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
113             fprintf(stderr, "\t10 bit stack mode disabled.\n");
114             options.stack10bit = 0;
115         }
116         else
117         {
118             /* Fixup the memory map for the stack; it is now in
119              * far space and requires a FPOINTER to access it.
120              */
121             istack->fmap = 1;
122             istack->ptrType = FPOINTER; 
123         }
124     }
125 }
126
127 static void _mcs51_setDefaultOptions(void)
128 {
129 }
130
131 static const char *_mcs51_getRegName(struct regs *reg)
132 {
133     if (reg)
134         return reg->name;
135     return "err";
136 }
137
138 static void _mcs51_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    }
149 }
150
151 /* Generate interrupt vector table. */
152 static int _mcs51_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
153 {
154     int i;
155     
156     if (options.model != MODEL_FLAT24)
157     {
158         /* Let the default code handle it. */
159         return FALSE;
160     }
161     
162     fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
163     
164     /* now for the other interrupts */
165     for (i = 0; i < maxInterrupts; i++) 
166     {
167         if (interrupts[i])
168         {
169             fprintf(of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
170         }
171         else
172         {
173             fprintf(of, "\treti\n\t.ds\t7\n");
174         }
175     }
176     
177     return TRUE;
178 }
179
180 /** $1 is always the basename.
181     $2 is always the output file.
182     $3 varies
183     $l is the list of extra options that should be there somewhere...
184     MUST be terminated with a NULL.
185 */
186 static const char *_linkCmd[] = {
187     "aslink", "-nf", "$1", NULL
188 };
189
190 static const char *_asmCmd[] = {
191     "asx8051", "-plosgffc", "$1.asm", NULL
192 };
193
194 /* Globals */
195 PORT mcs51_port = {
196     "mcs51",
197     "MCU 8051",                 /* Target name */
198     {
199         TRUE,                   /* Emit glue around main */
200     },
201     {   
202         _asmCmd,
203         "-plosgffc",            /* Options with debug */
204         "-plosgff",             /* Options without debug */
205     },
206     {
207         _linkCmd
208     },
209     {
210         _defaultRules
211     },
212     {
213         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
214         1, 1, 2, 4, 1, 2, 3, 1, 4, 4
215     },
216     {
217         "XSEG    (XDATA)",
218         "STACK   (DATA)",
219         "CSEG    (CODE)",
220         "DSEG    (DATA)",
221         "ISEG    (DATA)",
222         "XSEG    (XDATA)",
223         "BSEG    (BIT)",
224         "RSEG    (DATA)",
225         "GSINIT  (CODE)",
226         "OSEG    (OVR,DATA)",
227         "GSFINAL (CODE)",
228         NULL,
229         NULL,
230         1
231     },
232     { 
233         +1, 1, 4, 1, 1
234     },
235     /* mcs51 has an 8 bit mul */
236     {
237         1
238     },
239     "_",
240     _mcs51_init,
241     _mcs51_parseOptions,
242     _mcs51_finaliseOptions,
243     _mcs51_setDefaultOptions,
244     mcs51_assignRegisters,
245     _mcs51_getRegName ,
246     _mcs51_keywords,
247     _mcs51_genAssemblerPreamble,
248     _mcs51_genIVT ,
249     _mcs51_reset_regparm,
250     _mcs51_regparm,
251     NULL
252 };
253