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