2001-10-21 Michael Hope <michaelh@juju.net.nz>
[fw/sdcc] / 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 ()
46 {
47         regParmFlg = 0;
48 }
49
50 static int
51 _avr_regparm (sym_link * l)
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 (eBBlock ** ebbs, int count);
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 (FILE * of, symbol ** interrupts, int maxInterrupts)
130 {
131         return TRUE;
132 }
133
134 /** $1 is always the basename.
135     $2 is always the output file.
136     $3 varies
137     $l is the list of extra options that should be there somewhere...
138     MUST be terminated with a NULL.
139 */
140 static const char *_linkCmd[] = {
141         "linkavr", "", "$1", NULL
142 };
143
144 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
145 static const char *_asmCmd[] = {
146         "asavr", "$l" , "$3", "$1.s", NULL
147 };
148
149 /* Globals */
150 PORT avr_port = {
151         TARGET_ID_AVR,
152         "avr",
153         "ATMEL AVR",            /* Target name */
154         {
155          TRUE,                  /* Emit glue around main */
156          MODEL_LARGE | MODEL_SMALL,
157          MODEL_SMALL},
158         {
159          _asmCmd,
160          NULL,
161          "-plosgff",            /* Options with debug */
162          "-plosgff",            /* Options without debug */
163          0,
164         ".s"},
165         {
166          _linkCmd,
167          NULL,
168          NULL,
169          ".rel"},
170         {
171          _defaultRules},
172         {
173          /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
174          1, 2, 2, 4, 2, 2, 3, 1, 4, 4},
175         {
176          "XSEG",
177          "STACK",
178          "CSEG",
179          "DSEG",
180          "ISEG",
181          "XSEG",
182          "BSEG",
183          "RSEG",
184          "GSINIT",
185          "OSEG",
186          "GSFINAL",
187          "HOME",
188          NULL,
189          NULL,
190          0,
191          },
192         {
193          -1, 1, 4, 1, 1, 0},
194         /* avr has an 8 bit mul */
195         {
196           1, -1
197         },
198         "_",
199         _avr_init,
200         _avr_parseOptions,
201         _avr_finaliseOptions,
202         _avr_setDefaultOptions,
203         avr_assignRegisters,
204         _avr_getRegName,
205         _avr_keywords,
206         _avr_genAssemblerPreamble,
207         _avr_genIVT,
208         _avr_reset_regparm,
209         _avr_regparm,
210         NULL,
211         NULL,
212         NULL,
213         FALSE,
214         0,                      /* leave lt */
215         1,                      /* transform gt ==> not le */
216         0,                      /* leave le */
217         0,                      /* leave ge */
218         0,                      /* leave !=  */
219         0,                      /* leave == */
220         FALSE,                        /* No array initializer support. */
221         PORT_MAGIC
222 };