* src/pic16/device.h (pic16_options_t): added field use_crt,
[fw/sdcc] / device / lib / pic16 / startup / crt0iz.c
1 /*
2  * crt0iz.c - SDCC pic16 port runtime start code with
3  *            initialisation and RAM memory zero
4  *
5  * Converted for SDCC and pic16 port
6  * by Vangelis Rokas (vrokas@otenet.gr)
7  *
8  * based on Microchip MPLAB-C18 startup files
9  *
10  * $Id$
11  */
12
13 extern stack;
14 extern stack_end;
15
16 extern TBLPTRU;
17 extern TBLPTRH;
18 extern TBLPTRL;
19 extern FSR0L;
20 extern FSR0H;
21 extern TABLAT;
22 extern POSTINC0;
23 extern POSTDEC0;
24
25 /* global variable for forcing gplink to add _cinit section */
26 char __uflags = 0;
27
28 /* external reference to the user's main routine */
29 extern void main (void);
30
31 /* prototype for the startup function */
32 void _entry (void) _naked interrupt 0;
33 void _startup (void);
34
35 /* prototype for the initialized data setup */
36 void _do_cinit (void);
37
38
39 /*
40  * entry function, placed at interrupt vector 0 (RESET)
41  */
42
43 void _entry (void) _naked interrupt 0
44 {
45   _asm goto __startup _endasm;
46 }
47
48
49 void _startup (void)
50 {
51         _asm
52                 // Initialize the stack pointer
53                 lfsr 1, _stack_end
54                 lfsr 2, _stack_end
55                 clrf _TBLPTRU, 0        // 1st silicon doesn't do this on POR
56     
57                 // initialize the flash memory access configuration. this is harmless
58                 // for non-flash devices, so we do it on all parts.
59                 bsf 0xa6, 7, 0
60                 bcf 0xa6, 6, 0
61
62         _endasm ;
63     
64         /* cleanup the RAM */
65         _asm
66                 /* load FSR0 with top of RAM memory */
67                 movlw 0xff
68                 movwf _FSR0L, 0
69                 movlw 0x0e
70                 movwf _FSR0H, 0
71                 
72                 /* place a 1 at address 0x00, as a marker 
73                  * we haven't reached yet to it */
74                 movlw 1
75                 movwf 0x00, 0
76                 
77                 /* load WREG with zero */
78                 movlw 0x00
79                 
80 clear_loop:
81                 movwf _POSTDEC0, 0
82                 movf 0x00, 1, 0
83                 bnz clear_loop
84         _endasm ;
85
86
87         _do_cinit();
88
89         /* Call the user's main routine */
90         main ();
91
92 loop:
93         /* return from main will lock up */
94         goto loop;
95 }
96
97
98 /* the cinit table will be filled by the linker */
99 extern code struct
100 {
101   unsigned short num_init;
102   struct _init_entry {
103     unsigned long from;
104     unsigned long to;
105     unsigned long size;
106   } entries[];
107 } cinit;
108
109
110 #define tblrdpostinc    tblrd*+
111
112 /* the variable initialisation routine */
113 void _do_cinit (void)
114 {
115   /*
116    * we'll make the assumption in the following code that these statics
117    * will be allocated into the same bank.
118    */
119   static short long prom;
120   static unsigned short curr_byte;
121   static unsigned short curr_entry;
122   static short long data_ptr;
123
124
125         /* TBLPTR = &cinit */
126         _asm
127                 movlw low(_cinit)
128                 movwf _TBLPTRL, 0
129                 movlw high(_cinit)
130                 movwf _TBLPTRH, 0
131                 movlw upper(_cinit)
132                 movwf _TBLPTRU, 0
133         _endasm;
134
135         
136         /* curr_entry = cinit.num_init */
137         _asm
138                 movlb __do_cinit_data_ptr_1_1
139                 tblrdpostinc
140                 movf _TABLAT, 0, 0
141                 movwf __do_cinit_curr_entry_1_1, 1
142                 tblrdpostinc
143                 movf _TABLAT, 0, 0
144                 movwf __do_cinit_curr_entry_1_1+1, 1
145         _endasm;
146
147
148         //while (curr_entry) {
149         _asm
150 test:
151         bnz done1
152         tstfsz __do_cinit_curr_entry_1_1, 1
153         bra cont1
154
155 done1:
156         goto done
157
158 cont1:
159         _endasm;
160
161
162       /* Count down so we only have to look up the data in _cinit
163        * once.
164        *
165        * At this point we know that TBLPTR points to the top of the current
166        * entry in _cinit, so we can just start reading the from, to, and
167        * size values.
168        */
169         _asm
170                 
171                 /* read the source address low */
172                 tblrdpostinc
173                 movf _TABLAT, 0, 0
174                 movwf __do_cinit_prom_1_1, 1
175                 
176                 /* source address high */
177                 tblrdpostinc
178                 movf _TABLAT, 0, 0
179                 movwf __do_cinit_prom_1_1 + 1, 1
180
181                 /* source address upper */
182                 tblrdpostinc
183                 movf _TABLAT, 0, 0
184                 movwf __do_cinit_prom_1_1 + 2, 1
185
186                 /* skip a byte since it's stored as a 32bit int */
187                 tblrdpostinc
188
189                 /* read the destination address directly into FSR0 */
190                 /* destination address low */
191                 tblrdpostinc
192                 movf _TABLAT, 0, 0
193                 movwf _FSR0L, 0
194
195                 /* destination address high */
196                 tblrdpostinc
197                 movf _TABLAT, 0, 0
198                 movwf _FSR0H, 0
199
200                 /* skip two bytes since it's stored as a 32bit int */
201                 tblrdpostinc
202                 tblrdpostinc
203
204                 /* read the destination address directly into FSR0 */
205                 tblrdpostinc
206                 movf _TABLAT, 0, 0
207                 movwf __do_cinit_curr_byte_1_1, 1
208                 tblrdpostinc
209                 movf _TABLAT, 0, 0
210                 movwf __do_cinit_curr_byte_1_1+1, 1
211
212                 /* skip two bytes since it's stored as a 32bit int */
213                 tblrdpostinc
214                 tblrdpostinc
215         _endasm;
216
217         //prom = data_ptr->from;
218         //FSR0 = data_ptr->to;
219         //curr_byte = (unsigned short) data_ptr->size;
220         /* the table pointer now points to the next entry. Save it
221          * off since we'll be using the table pointer to do the copying
222          * for the entry */
223   
224         /*  data_ptr = TBLPTR */
225         _asm
226                 movff _TBLPTRL, __do_cinit_data_ptr_1_1
227                 movff _TBLPTRH, __do_cinit_data_ptr_1_1 + 1
228                 movff _TBLPTRU, __do_cinit_data_ptr_1_1 + 2
229         _endasm;
230   
231       
232         /* now assign the source address to the table pointer */
233         /*  TBLPTR = prom */
234         _asm
235                 movff __do_cinit_prom_1_1, _TBLPTRL
236                 movff __do_cinit_prom_1_1 + 1, _TBLPTRH
237                 movff __do_cinit_prom_1_1 + 2, _TBLPTRU
238         _endasm;
239
240         /* do the copy loop */
241         _asm
242
243                 /* determine if we have any more bytes to copy */
244                 movlb __do_cinit_curr_byte_1_1
245                 movf __do_cinit_curr_byte_1_1, 1, 1
246 copy_loop:
247                 bnz copy_one_byte // copy_one_byte
248                 movf __do_cinit_curr_byte_1_1 + 1, 1, 1
249                 bz done_copying
250
251 copy_one_byte:
252                 tblrdpostinc
253                 movf _TABLAT, 0, 0
254                 movwf _POSTINC0, 0
255
256                 /* decrement byte counter */
257                 decf __do_cinit_curr_byte_1_1, 1, 1
258                 bnc copy_loop // copy_loop
259                 decf __do_cinit_curr_byte_1_1 + 1, 1, 1
260
261                 bra copy_loop
262 done_copying:
263         _endasm;
264   
265         /* restore the table pointer for the next entry */
266         /*  TBLPTR = data_ptr */
267         _asm
268                 movff __do_cinit_data_ptr_1_1, _TBLPTRL
269                 movff __do_cinit_data_ptr_1_1 + 1, _TBLPTRH
270                 movff __do_cinit_data_ptr_1_1 + 2, _TBLPTRU
271         _endasm;
272
273   
274         /* next entry... */
275         curr_entry--;
276
277         _asm
278                 goto test;
279
280         /* emit done label */
281 done:
282         _endasm;
283 }
284