Implemented builtin functions
[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 {
20   "at",
21   "bit",
22   "code",
23   "critical",
24   "data",
25   "far",
26   "idata",
27   "interrupt",
28   "near",
29   "pdata",
30   "reentrant",
31   "sfr",
32   "sbit",
33   "using",
34   "xdata",
35   "_data",
36   "_code",
37   "_generic",
38   "_near",
39   "_xdata",
40   "_pdata",
41   "_idata",
42   "_naked",
43   NULL
44 };
45
46
47 void mcs51_assignRegisters (eBBlock ** ebbs, int count);
48
49 static int regParmFlg = 0;      /* determine if we can register a parameter */
50
51 static void
52 _mcs51_init (void)
53 {
54   asm_addTree (&asm_asxxxx_mapping);
55 }
56
57 static void
58 _mcs51_reset_regparm ()
59 {
60   regParmFlg = 0;
61 }
62
63 static int
64 _mcs51_regparm (sym_link * l)
65 {
66   /* for this processor it is simple
67      can pass only the first parameter in a register */
68   if (regParmFlg)
69     return 0;
70
71   regParmFlg = 1;
72   return 1;
73 }
74
75 static bool
76 _mcs51_parseOptions (int *pargc, char **argv, int *i)
77 {
78   /* TODO: allow port-specific command line options to specify
79    * segment names here.
80    */
81   return FALSE;
82 }
83
84 static void
85 _mcs51_finaliseOptions (void)
86 {
87   if (options.model == MODEL_LARGE) {
88       port->mem.default_local_map = xdata;
89       port->mem.default_globl_map = xdata;
90     }
91   else
92     {
93       port->mem.default_local_map = data;
94       port->mem.default_globl_map = data;
95     }
96 }
97
98 static void
99 _mcs51_setDefaultOptions (void)
100 {
101 }
102
103 static const char *
104 _mcs51_getRegName (struct regs *reg)
105 {
106   if (reg)
107     return reg->name;
108   return "err";
109 }
110
111 static void
112 _mcs51_genAssemblerPreamble (FILE * of)
113 {
114 }
115
116 /* Generate interrupt vector table. */
117 static int
118 _mcs51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
119 {
120   return FALSE;
121 }
122
123 /* Do CSE estimation */
124 static bool cseCostEstimation (iCode *ic, iCode *pdic)
125 {
126     operand *result = IC_RESULT(ic);
127     operand *right  = IC_RIGHT(ic);
128     operand *left   = IC_LEFT(ic);
129     sym_link *result_type = operandType(result);
130     sym_link *right_type  = (right ? operandType(right) : 0);
131     sym_link *left_type   = (left  ? operandType(left)  : 0);
132
133     /* if it is a pointer then return ok for now */
134     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
135     
136     /* if bitwise | add & subtract then no since mcs51 is pretty good at it 
137        so we will cse only if they are local (i.e. both ic & pdic belong to
138        the same basic block */
139     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
140         /* then if they are the same Basic block then ok */
141         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
142         else return 0;
143     }
144         
145     /* for others it is cheaper to do the cse */
146     return 1;
147 }
148
149 /** $1 is always the basename.
150     $2 is always the output file.
151     $3 varies
152     $l is the list of extra options that should be there somewhere...
153     MUST be terminated with a NULL.
154 */
155 static const char *_linkCmd[] =
156 {
157   "{bindir}{sep}aslink", "-nf", "$1", NULL
158 };
159
160 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
161 static const char *_asmCmd[] =
162 {
163   "asx8051", "$l", "$3", "$1.asm", NULL
164 };
165
166 /* Globals */
167 PORT mcs51_port =
168 {
169   TARGET_ID_MCS51,
170   "mcs51",
171   "MCU 8051",                   /* Target name */
172   {
173     TRUE,                       /* Emit glue around main */
174     MODEL_SMALL | MODEL_LARGE,
175     MODEL_SMALL
176   },
177   {
178     _asmCmd,
179     NULL,
180     "-plosgffc",                /* Options with debug */
181     "-plosgff",                 /* Options without debug */
182     0,
183     ".asm"
184   },
185   {
186     _linkCmd,
187     NULL,
188     NULL,
189     ".rel"
190   },
191   {
192     _defaultRules
193   },
194   {
195         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
196     1, 2, 2, 4, 1, 2, 3, 1, 4, 4
197   },
198   {
199     "XSEG    (XDATA)",
200     "STACK   (DATA)",
201     "CSEG    (CODE)",
202     "DSEG    (DATA)",
203     "ISEG    (DATA)",
204     "XSEG    (XDATA)",
205     "BSEG    (BIT)",
206     "RSEG    (DATA)",
207     "GSINIT  (CODE)",
208     "OSEG    (OVR,DATA)",
209     "GSFINAL (CODE)",
210     "HOME        (CODE)",
211     NULL,
212     NULL,
213     1
214   },
215   {
216     +1, 1, 4, 1, 1, 0
217   },
218     /* mcs51 has an 8 bit mul */
219   {
220     1, -1
221   },
222   "_",
223   _mcs51_init,
224   _mcs51_parseOptions,
225   _mcs51_finaliseOptions,
226   _mcs51_setDefaultOptions,
227   mcs51_assignRegisters,
228   _mcs51_getRegName,
229   _mcs51_keywords,
230   _mcs51_genAssemblerPreamble,
231   _mcs51_genIVT,
232   _mcs51_reset_regparm,
233   _mcs51_regparm,
234   NULL,
235   NULL,
236   NULL,
237   FALSE,
238   0,                            /* leave lt */
239   0,                            /* leave gt */
240   1,                            /* transform <= to ! > */
241   1,                            /* transform >= to ! < */
242   1,                            /* transform != to !(a == b) */
243   0,                            /* leave == */
244   FALSE,                        /* No array initializer support. */
245   cseCostEstimation,
246   NULL,                         /* no builtin functions */
247   PORT_MAGIC
248 };