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