Imported Upstream version 2.9.0
[debian/cc1111] / src / avr / main.c
1 /** @file main.c
2     avr specific general functions.
3
4     Note that mlh prepended _avr_ 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 #include "peeph.rul"
14 };
15
16 /* list of key words used by msc51 */
17 static char *_avr_keywords[] = {
18         "at",
19         "code",
20         "critical",
21         "eeprom",
22         "interrupt",
23         "sfr",
24         "xdata",
25         "_code",
26         "_eeprom",
27         "_generic",
28         "_xdata",
29         "sram",
30         "_sram",
31         "flash",
32         "_flash",
33         NULL
34 };
35
36 static int regParmFlg = 0;      /* determine if we can register a parameter */
37
38 static void
39 _avr_init (void)
40 {
41         asm_addTree (&asm_asxxxx_mapping);
42 }
43
44 static void
45 _avr_reset_regparm (void)
46 {
47         regParmFlg = 0;
48 }
49
50 static int
51 _avr_regparm (sym_link * l, bool reentrant)
52 {
53         /* the first eight bytes will be passed in
54            registers r16-r23. but we won't split variables
55            i.e. if not enough registers left to hold
56            the parameter then the whole parameter along
57            with rest of the parameters go onto the stack */
58         if (regParmFlg < 8) {
59                 int size;
60                 if ((size = getSize (l)) > (8 - regParmFlg)) {
61                         /* all remaining go on stack */
62                         regParmFlg = 8;
63                         return 0;
64                 }
65                 regParmFlg += size;
66                 return 1;
67         }
68
69         return 0;
70 }
71
72 void avr_assignRegisters (ebbIndex *);
73
74 static bool
75 _avr_parseOptions (int *pargc, char **argv, int *i)
76 {
77         /* TODO: allow port-specific command line options to specify
78          * segment names here.
79          */
80         return FALSE;
81 }
82
83 static void
84 _avr_finaliseOptions (void)
85 {
86         port->mem.default_local_map = port->mem.default_globl_map = xdata;
87         /* change stack to be in far space */
88         /* internal stack segment ;   
89            SFRSPACE       -   NO
90            FAR-SPACE      -   YES
91            PAGED          -   NO
92            DIRECT-ACCESS  -   NO
93            BIT-ACCESS     -   NO
94            CODE-ACESS     -   NO 
95            DEBUG-NAME     -   'B'
96            POINTER-TYPE   -   FPOINTER
97          */
98         istack =
99                 allocMap (0, 1, 0, 0, 0, 0, options.stack_loc, ISTACK_NAME,
100                           'B', FPOINTER);
101
102         /* also change xdata to be direct space since we can use lds/sts */
103         xdata->direct = 1;
104
105 }
106
107 static void
108 _avr_setDefaultOptions (void)
109 {
110         options.stackAuto = 1;
111 }
112
113 static const char *
114 _avr_getRegName (struct regs *reg)
115 {
116         if (reg)
117                 return reg->name;
118         return "err";
119 }
120
121 static void
122 _avr_genAssemblerPreamble (FILE * of)
123 {
124
125 }
126
127 /* Generate interrupt vector table. */
128 static int
129 _avr_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
130 {
131   return TRUE;
132 }
133
134 /* Indicate which extended bit operations this port supports */
135 static bool
136 hasExtBitOp (int op, int size)
137 {
138   if (op == RRC
139       || op == RLC
140       || op == GETHBIT
141      )
142     return TRUE;
143   else
144     return FALSE;
145 }
146
147 /* Indicate the expense of an access to an output storage class */
148 static int
149 oclsExpense (struct memmap *oclass)
150 {
151   if (IN_FARSPACE(oclass))
152     return 1;
153     
154   return 0;
155 }
156
157 /** $1 is always the basename.
158     $2 is always the output file.
159     $3 varies
160     $l is the list of extra options that should be there somewhere...
161     MUST be terminated with a NULL.
162 */
163 static const char *_linkCmd[] = {
164         "linkavr", "", "\"$1\"", NULL
165 };
166
167 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
168 static const char *_asmCmd[] = {
169         "asavr", "$l" , "$3", "\"$1.s\"", NULL
170 };
171
172 /* Globals */
173 PORT avr_port = {
174         TARGET_ID_AVR,
175         "avr",
176         "ATMEL AVR",            /* Target name */
177         NULL,                   /* processor */
178         {
179          glue,
180          TRUE,                  /* Emit glue around main */
181          MODEL_LARGE | MODEL_SMALL,
182          MODEL_SMALL
183         },
184         {
185          _asmCmd,
186          NULL,
187          "-plosgff",            /* Options with debug */
188          "-plosgff",            /* Options without debug */
189          0,
190         ".s",
191          NULL,                  /* no do_assemble */
192         },
193         {
194          _linkCmd,
195          NULL,
196          NULL,
197          ".rel",
198          1},
199         {
200          _defaultRules},
201         {
202          /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
203          1, 2, 2, 4, 2, 2, 3, 1, 4, 4},
204         
205          /* tags for generic pointers */
206         { 0x00, 0x40, 0x60, 0x80 },             /* far, near, xstack, code */
207         
208         {
209          "XSEG",
210          "STACK",
211          "CSEG",
212          "DSEG",
213          "ISEG",
214          NULL, //PSEG
215          "XSEG",
216          "BSEG",
217          "RSEG",
218          "GSINIT",
219          "OSEG",
220          "GSFINAL",
221          "HOME",
222          NULL, // initialized xdata
223          NULL, // a code copy of xiseg
224          "CONST   (CODE)",           // const_name - const data (code or not)
225          "CABS    (ABS,CODE)",       // cabs_name - const absolute data (code or not)
226          "XABS    (ABS,XDATA)",      // xabs_name - absolute xdata/pdata
227          "IABS    (ABS,DATA)",       // iabs_name - absolute idata/data
228          NULL,
229          NULL,
230          0,
231          },
232         { NULL, NULL },
233         {
234          -1, 1, 4, 1, 1, 0},
235         /* avr has an 8 bit mul */
236         {
237           1, -1
238         },
239         {
240           avr_emitDebuggerSymbol
241         },
242         {
243           255/3,      /* maxCount */
244           3,          /* sizeofElement */
245           /* The rest of these costs are bogus. They approximate */
246           /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
247           {4,4,4},    /* sizeofMatchJump[] */
248           {0,0,0},    /* sizeofRangeCompare[] */
249           0,          /* sizeofSubtract */
250           3,          /* sizeofDispatch */
251         },
252         "_",
253         _avr_init,
254         _avr_parseOptions,
255         NULL,
256         NULL,
257         _avr_finaliseOptions,
258         _avr_setDefaultOptions,
259         avr_assignRegisters,
260         _avr_getRegName,
261         _avr_keywords,
262         _avr_genAssemblerPreamble,
263         NULL,                           /* no genAssemblerEnd */
264         _avr_genIVT,
265         NULL, // _avr_genXINIT
266         NULL,                   /* genInitStartup */
267         _avr_reset_regparm,
268         _avr_regparm,
269         NULL,
270         NULL,
271         NULL,
272         hasExtBitOp,            /* hasExtBitOp */
273         oclsExpense,            /* oclsExpense */
274         FALSE,
275         TRUE,                   /* little endian */
276         0,                      /* leave lt */
277         1,                      /* transform gt ==> not le */
278         0,                      /* leave le */
279         0,                      /* leave ge */
280         0,                      /* leave !=  */
281         0,                      /* leave == */
282         FALSE,                  /* No array initializer support. */
283         0,                      /* no CSE cost estimation yet */
284         NULL,                   /* no builtin functions */
285         GPOINTER,               /* treat unqualified pointers as "generic" pointers */
286         1,                      /* reset labelKey to 1 */
287         1,                      /* globals & local static allowed */
288         PORT_MAGIC
289 };