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