now it almost assembles using Paul's xa_asm.
[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_asxxxx_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   // this needs to be an include file someday
118   fputs ("pswl\tsfr\t0x400\n", of);
119   fputs ("z\tbit\tpswl.0\n", of);
120   fputs ("n\tbit\tpswl.1\n", of);
121   fputs ("v\tbit\tpswl.2\n", of);
122   fputs ("ac\tbit\tpswl.6\n", of);
123   fputs ("cy\tbit\tpswl.7\n", of);
124 }
125
126 /* Generate interrupt vector table. */
127 static int
128 _xa51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
129 {
130   return FALSE;
131 }
132
133 /* Generate code to copy XINIT to XISEG */
134 static void _xa51_genXINIT (FILE * of) {
135   fprintf (of, ";       _xa51_genXINIT() start\n");
136   fprintf (of, "        mov     r0,#l_XINIT\n");
137   fprintf (of, "        beq     00002$\n");
138   fprintf (of, "        mov     r1,#s_XINIT\n");
139   fprintf (of, "        mov     r2,#s_XISEG\n");
140   fprintf (of, "00001$  movc    r3l,[r1+]\n");
141   fprintf (of, "        mov     [r2+],r3l\n");
142   fprintf (of, "        djnz    r0,00001$\n");
143   fprintf (of, "00002$:\n");
144   fprintf (of, ";       _xa51_genXINIT() end\n");
145 }
146
147
148 /* Do CSE estimation */
149 static bool cseCostEstimation (iCode *ic, iCode *pdic)
150 {
151     operand *result = IC_RESULT(ic);
152     sym_link *result_type = operandType(result);
153
154     /* if it is a pointer then return ok for now */
155     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
156     
157     /* if bitwise | add & subtract then no since xa51 is pretty good at it 
158        so we will cse only if they are local (i.e. both ic & pdic belong to
159        the same basic block */
160     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
161         /* then if they are the same Basic block then ok */
162         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
163         else return 0;
164     }
165         
166     /* for others it is cheaper to do the cse */
167     return 1;
168 }
169
170 /** $1 is always the basename.
171     $2 is always the output file.
172     $3 varies
173     $l is the list of extra options that should be there somewhere...
174     MUST be terminated with a NULL.
175 */
176 static const char *_linkCmd[] =
177 {
178   "{bindir}{sep}aslink", "-nf", "$1", NULL
179 };
180
181 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
182 static const char *_asmCmd[] =
183 {
184   "xa_asm", "$l", "$3", "$1.xa", NULL
185 };
186
187 /* Globals */
188 PORT xa51_port =
189 {
190   TARGET_ID_XA51,
191   "xa51",
192   "MCU 80C51XA",                /* Target name */
193   {
194     TRUE,                       /* Emit glue around main */
195     MODEL_LARGE,
196     MODEL_LARGE
197   },
198   {
199     _asmCmd,
200     NULL,
201     "",                         /* Options with debug */
202     "",                         /* Options without debug */
203     0,
204     ".xa",
205     NULL                        /* no do_assemble function */
206   },
207   {
208     _linkCmd,
209     NULL,
210     NULL,
211     ".rel"
212   },
213   {
214     _defaultRules
215   },
216   {
217         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
218     1, 2, 2, 4, 2, 2, 3, 1, 4, 4
219   },
220   {
221     "XSEG    (XDATA)",
222     "STACK   (DATA)",
223     "CSEG    (CODE)",
224     "DSEG    (DATA)",
225     "ISEG    (DATA)",
226     "XSEG    (XDATA)",
227     "BSEG    (BIT)",
228     "RSEG    (DATA)",
229     "GSINIT  (CODE)",
230     "OSEG    (OVR,DATA)",
231     "GSFINAL (CODE)",
232     "HOME    (CODE)",
233     "XISEG   (XDATA)", // initialized xdata
234     "XINIT   (CODE)", // a code copy of xiseg
235     NULL, // default local map
236     NULL, // default global map
237     1
238   },
239   {
240     -1, // stack grows down
241     0, // bank overhead NUY
242     6, // isr overhead
243     4, // function call overhead
244     0, // reentrant overhead NUY
245     0 // banked overhead NUY
246   },
247     /* xa51 has an 16 bit mul */
248   {
249     2, -2
250   },
251   "_",
252   _xa51_init,
253   _xa51_parseOptions,
254   _xa51_finaliseOptions,
255   _xa51_setDefaultOptions,
256   xa51_assignRegisters,
257   _xa51_getRegName,
258   _xa51_keywords,
259   _xa51_genAssemblerPreamble,
260   _xa51_genAssemblerEnd,
261   _xa51_genIVT,
262   _xa51_genXINIT,
263   _xa51_reset_regparm,
264   _xa51_regparm,
265   NULL, // process_pragma()
266   NULL, // getMangledFunctionName()
267   NULL, // hasNativeMulFor()
268   TRUE, // use_dw_for_init
269   0,                            /* leave lt */
270   0,                            /* leave gt */
271   0,                            /* transform <= to ! > */
272   0,                            /* transform >= to ! < */
273   0,                            /* transform != to !(a == b) */
274   0,                            /* leave == */
275   FALSE,                        /* No array initializer support. */
276   cseCostEstimation,
277   NULL,                         /* no builtin functions */
278   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
279   1,                            /* reset labelKey to 1 */
280   1,                            /* globals & local static allowed */
281   PORT_MAGIC
282 };