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