xa51, work in progress
[fw/sdcc] / src / xa51 / main.c
1 /** @file main.c
2     xa51 specific general functions.
3
4     Note that mlh prepended _xa51_ 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 xa51 */
18 static char *_xa51_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   "_overlay",
44   NULL
45 };
46
47 extern int rewinds;
48 void   _xa51_genAssemblerEnd () {
49   //fprintf (stderr, "Did %d rewind%c for c-line in asm comments\n", rewinds,
50   //rewinds==1 ? '\0' : 's');
51 }
52
53 void xa51_assignRegisters (eBBlock ** ebbs, int count);
54
55 static int regParmFlg = 0;      /* determine if we can register a parameter */
56
57 static void
58 _xa51_init (void)
59 {
60   asm_addTree (&asm_xa_asm_mapping);
61 }
62
63 static void
64 _xa51_reset_regparm ()
65 {
66   regParmFlg = 0;
67 }
68
69 static int
70 _xa51_regparm (sym_link * l)
71 {
72   return 0; // for now
73   /* for this processor it is simple
74      can pass only the first parameter in a register */
75   if (regParmFlg)
76     return 0;
77
78   regParmFlg = 1;
79   return 1;
80 }
81
82 static bool
83 _xa51_parseOptions (int *pargc, char **argv, int *i)
84 {
85   /* TODO: allow port-specific command line options to specify
86    * segment names here.
87    */
88   return FALSE;
89 }
90
91 static void
92 _xa51_finaliseOptions (void)
93 {
94   port->mem.default_local_map = istack;
95   port->mem.default_globl_map = xdata;
96 }
97
98 static void
99 _xa51_setDefaultOptions (void)
100 {
101   options.stackAuto=1;
102   options.intlong_rent=1;
103   options.float_rent=1;
104 }
105
106 static const char *
107 _xa51_getRegName (struct regs *reg)
108 {
109   if (reg)
110     return reg->name;
111   return "err";
112 }
113
114 static void
115 _xa51_genAssemblerPreamble (FILE * of)
116 {
117   fprintf (of, "_errno\tsfr\t0x00; to keep the fp-lib's happy for now\n");
118 }
119
120 /* Generate interrupt vector table. */
121 static int
122 _xa51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
123 {
124   fprintf (of, "\t.dw\t0x8f00\n");
125   fprintf (of, "\t.dw\t__sdcc_gsinit_startup\n");
126   // no IVT yet
127   return TRUE;
128 }
129
130 /* Generate code to copy XINIT to XISEG */
131 static void _xa51_genXINIT (FILE * of) {
132   fprintf (of, ";       _xa51_genXINIT() start\n");
133   fprintf (of, "        mov     r0,#l_XINIT\n");
134   fprintf (of, "        beq     00002$\n");
135   fprintf (of, "        mov     r1,#s_XINIT\n");
136   fprintf (of, "        mov     r2,#s_XISEG\n");
137   fprintf (of, "00001$  movc    r3l,[r1+]\n");
138   fprintf (of, "        mov     [r2+],r3l\n");
139   fprintf (of, "        djnz    r0,00001$\n");
140   fprintf (of, "00002$:\n");
141   fprintf (of, ";       _xa51_genXINIT() end\n");
142 }
143
144
145 /* Do CSE estimation */
146 static bool cseCostEstimation (iCode *ic, iCode *pdic)
147 {
148     operand *result = IC_RESULT(ic);
149     sym_link *result_type = operandType(result);
150
151     /* if it is a pointer then return ok for now */
152     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
153     
154     /* if bitwise | add & subtract then no since xa51 is pretty good at it 
155        so we will cse only if they are local (i.e. both ic & pdic belong to
156        the same basic block */
157     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
158         /* then if they are the same Basic block then ok */
159         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
160         else return 0;
161     }
162         
163     /* for others it is cheaper to do the cse */
164     return 1;
165 }
166
167 /** $1 is always the basename.
168     $2 is always the output file.
169     $3 varies
170     $l is the list of extra options that should be there somewhere...
171     MUST be terminated with a NULL.
172 */
173 static const char *_linkCmd[] =
174 {
175   "{bindir}{sep}aslink", "-nf", "$1", NULL
176 };
177
178 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
179 static const char *_asmCmd[] =
180 {
181   "xa_asm", "$l", "$3", "$1.xa", NULL
182 };
183
184 /* Globals */
185 PORT xa51_port =
186 {
187   TARGET_ID_XA51,
188   "xa51",
189   "MCU 80C51XA",                /* Target name */
190   {
191     TRUE,                       /* Emit glue around main */
192     MODEL_LARGE,
193     MODEL_LARGE
194   },
195   {
196     _asmCmd,
197     NULL,
198     "",                         /* Options with debug */
199     "",                         /* Options without debug */
200     0,
201     ".xa",
202     NULL                        /* no do_assemble function */
203   },
204   {
205     _linkCmd,
206     NULL,
207     NULL,
208     ".rel"
209   },
210   {
211     _defaultRules
212   },
213   {
214         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
215     1, 2, 2, 4, 2, 2, 3, 1, 4, 4
216   },
217   {
218     "XSEG    (XDATA)",
219     "STACK   (DATA)",
220     "CSEG    (CODE)",
221     "DSEG    (DATA)",
222     "ISEG    (DATA)",
223     "XSEG    (XDATA)",
224     "BSEG    (BIT)",
225     "RSEG    (DATA)",
226     "GSINIT  (CODE)",
227     "OSEG    (OVR,DATA)",
228     "GSFINAL (CODE)",
229     "HOME    (CODE)",
230     "XISEG   (XDATA)", // initialized xdata
231     "XINIT   (CODE)", // a code copy of xiseg
232     NULL, // default local map
233     NULL, // default global map
234     1
235   },
236   {
237     -1, // stack grows down
238     0, // bank overhead NUY
239     6, // isr overhead
240     4, // function call overhead
241     0, // reentrant overhead NUY
242     0 // banked overhead NUY
243   },
244     /* xa51 has an 16 bit mul */
245   {
246     2, -2
247   },
248   "_",
249   _xa51_init,
250   _xa51_parseOptions,
251   _xa51_finaliseOptions,
252   _xa51_setDefaultOptions,
253   xa51_assignRegisters,
254   _xa51_getRegName,
255   _xa51_keywords,
256   _xa51_genAssemblerPreamble,
257   _xa51_genAssemblerEnd,
258   _xa51_genIVT,
259   _xa51_genXINIT,
260   _xa51_reset_regparm,
261   _xa51_regparm,
262   NULL, // process_pragma()
263   NULL, // getMangledFunctionName()
264   NULL, // hasNativeMulFor()
265   TRUE, // use_dw_for_init
266   0,                            /* leave lt */
267   0,                            /* leave gt */
268   0,                            /* transform <= to ! > */
269   0,                            /* transform >= to ! < */
270   0,                            /* transform != to !(a == b) */
271   0,                            /* leave == */
272   FALSE,                        /* No array initializer support. */
273   cseCostEstimation,
274   NULL,                         /* no builtin functions */
275   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
276   1,                            /* reset labelKey to 1 */
277   1,                            /* globals & local static allowed */
278   PORT_MAGIC
279 };